10
$\begingroup$

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} *)
$\endgroup$
  • $\begingroup$ Related: (8829) $\endgroup$ – Mr.Wizard Sep 19 '15 at 18:53
  • $\begingroup$ I disagree with the close votes. This is a subtle error not explained at all in the documentation, AFAICS. There are valid reasons for using Set instead of SetDelayed as well as reasons for putting constraints on patterns. $\endgroup$ – Michael E2 Oct 21 '15 at 11:30
  • 1
    $\begingroup$ @Mr.Wizard not just related, but already covered and answered there, I think. $\endgroup$ – LLlAMnYP Oct 21 '15 at 11:52
17
$\begingroup$

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]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.