Why does my function defined with constraints on patterns not work? [duplicate]

Possible Duplicate:
Why doesn't PatternTest work with Composition?

My function is something like this,

a[x_Real?(# > 0) &] := Plot[x*Sin[y], {y, 0, 10}];

But, a returns nothing but a.

This function doesn't work either,

a[x_Real/;(# > 0) &] := Plot[x*Sin[y], {y, 0, 10}];

I'm very much confused. Can anybody tell me why these won't work?

marked as duplicate by rcollyer, Mr.Wizard♦Jun 18 '12 at 16:11

There are two issues here. The first one has to do with the order of precedence. In Mathematica, the precedence of & is very low which means that the expression x_Real?(# > 0) & is interpreted as (x_Real?(# > 0))&. What you actually want is x_Real?(# > 0 &).

The other, minor, issue is that 5 has head Integer, not Real, so MatchQ[5, _Real] returns False. This could be solved by matching for _?NumericQ instead. However, since a>0 implies that a is a real number, this condition isn't actually necessary in this case. In summery, you could do something like

a[x_?(# > 0 &)] := Plot[x*Sin[y], {y, 0, 10}];

By the way, to check in which order operators are executed you can repeatedly click on an expression. The order in which extra parts of the expression are highlighted indicates in which order the expression will be executed.

The error is in the placement of &. Looking at the FullForm of the left hand sides

FullForm[a[x_Real?(# > 0) &]]
(*
a[Function[PatternTest[Pattern[x,Blank[Real]],Greater[Slot,0]]]]
*)

and

FullForm[a[x_Real /; (# > 0) &]]
(*
a[Function[Condition[Pattern[x,Blank[Real]],Greater[Slot,0]]]]
*)

shows that, in both cases the entire pattern is considered part of the function. To solve this, simply move the ampersand (&) inside the parantheses. In other words,

a[x_Real?(# > 0&)] := Plot[x*Sin[y], {y, 0, 10}];
a[x_Real/;(# > 0&)] := Plot[x*Sin[y], {y, 0, 10}];

Edit: This includes an explanation, now, about why the form using Condition, above, does not work.

However, the condition will not work as expected as it does not apply a function to the parameter, but evaluates the condition with the variable set to its passed in value. It is equivalent to this

TrueQ@Block[{x = (* some value *)}, (* condition *)]

In your case, the condition is # > 0&, so TrueQ will return False. Instead you want to use the variables name inside of the condition, as follows

a[x_Real/;(x > 0)] := Plot[x*Sin[y], {y, 0, 10}];

As pointed out by Heike, there is another problem: 5 is interpreted by Mathematica as Integer not Real, so a will only return a. There are two ways to handle this, fix it by removing the restriction

a[x_?(# > 0&)] := Plot[x*Sin[y], {y, 0, 10}];
a[x_/;(x > 0)] := Plot[x*Sin[y], {y, 0, 10}];

or, ensure that a real number is passed: Try for example

a[x_ /; (x > 0)] := Plot[x*Sin[y], {y, 0, 10}];

Compare these results:

MatchQ[5., _Real]
True

MatchQ[5, _Real]
False

Mathematica distinguishes between 5. and just plain 5

The difference is that 5. is a floating point number which matches with Real and that 5 is simply a rational number.

• MatchQ[5, _Rational] yields False. – Artes Jun 18 '12 at 15:21