10

Maybe this question is so trivial but it has confused me.
I'm studying the What the @#%^&*?! do all those funny signs mean? and in the Rules and patterns under the Reference for the operator /; there is this example:

In[1]:= f[x_] := ppp[x] /; x > 0 
In[2]:= f[5]
Out[2]= ppp[5]
In[3]:= f[-6]
Out[3]= f[-6]  

Based on the above example I thought the answer of the following code should be f[-2], as the following:

In[1]:= f[x_] = Sqrt[x] /; x > 0
Out[1]= Sqrt[x] /; x > 0
In[2]:= f[2]
Out[2]= Sqrt[2] /; 2 > 0
In[3]:= f[-2]
Out[3]= f[-2]  

I mean the definition f[x_] = Sqrt[x] should only be used when x>0. So when I enter -2 as the argument, the definition should not be used and the output will be f[-2]. But in fact mathematica evaluates the code as follows:

In[1]:= f[x_] = Sqrt[x] /; x > 0
Out[1]= Sqrt[x] /; x > 0
In[2]:= f[2]
Out[2]= Sqrt[2] /; 2 > 0
In[3]:= f[-2]
Out[3]= i Sqrt[2] /; -2 > 0  

In spite of the fact that -2<0, Mathematica uses the definition and produces the answer $i\sqrt{2}$
What's the difference between this code and the first one that makes mathematica use the definition in spite of the negative argument passed to the function?


Update: Response to closure (Michael E2)

There must be something quite subtle going on. It is not just the usual explanation that Set evaluates the right-hand and SetDelayed does not, because the right-hand side evaluates to itself (assuming, as Mr. Wizard's answer points out, that x has no value). This can be seen because the down values are the same in each case:

f1[x_] := Sqrt[x] /; x > 0;
f2[x_] = Sqrt[x] /; x > 0;

DownValues@f1
DownValues@f2

(* {HoldPattern[f1[x_]] :> Sqrt[x] /; x > 0} *)
(* {HoldPattern[f2[x_]] :> Sqrt[x] /; x > 0} *)
Sepideh Abadpour
  • 967
  • 1
  • 9
  • 18

1 Answers1

17

When using Set rather than SetDelayed you will need to hang the Condition on the left-hand-side:

ClearAll[f]

f[x_] /; x > 0 = Sqrt[x]
f[2]
f[-2]
Sqrt[x]

Sqrt[2]

f[-2]

There are other reasons to prefer this placement; see:

However be aware that the use of Set results in "pre-evaluation" of the RHS which often is not desirable. For example suppose the global Symbol x has a value before the definition is made:

ClearAll[f]
x = 7;

f[x_] /; x > 0 = Sqrt[x]
f[2]
f[-2]
Sqrt[7]

Sqrt[7]

f[-2]

This is probably not what you want. Using := works:

ClearAll[f]

x = 7;

f[x_] /; x > 0 := Sqrt[x]
f[2]
f[-2]
Sqrt[2]

f[-2]

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371