0
$\begingroup$

I wanted to understand how Mathematica parses function definitions in rules-based programming, so I started with the simple code:

Clear[f];
f[x /; MatchQ[x, {_?NumericQ, _?NumericQ}]] := Total@x;
f[x_] := -1;
f[{1, 2.3}]
f[{4}]

As expected, the output is:

3.3
-1

Then I added another line:

Clear[f];
f[x /; MatchQ[x, {_?NumericQ, _?NumericQ}]] := Total@x;
f[x ;/ MatchQ[x, {_?NumericQ, 0}]] := (2 * x)[[1]];
f[x_] := -1;
f[{1, 2.3}]
f[{1, 0}]
f[{4}]

Interestingly, the output is now:

3.3
1
-1

So the second rule specification did not really override the first rule. But now, if I put that second rule before the first rule, like so:

Clear[f];
f[x ;/ MatchQ[x, {_?NumericQ, 0}]] := (2 * x)[[1]];
f[x /; MatchQ[x, {_?NumericQ, _?NumericQ}]] := Total@x;
f[x_] := -1;
f[{1, 2.3}]
f[{1, 0}]
f[{4}]

I get the expected output:

3.3
2
-1

So, I am guessing if I want multiple rules, I should put the more restrictive ones before the general ones. This way, Mathematica will be able to use the first match to execute the appropriate function. But now consider this:

Clear[f];
f[x_] := -1;
f[x /; MatchQ[x, {_?NumericQ, _?NumericQ}]] := Total@x;
f[x ;/ MatchQ[x, {_?NumericQ, 0}]] := (2 * x)[[1]];
f[{1, 2.3}]
f[{1, 0}]
f[{4}]

The most general rule is at the top, yet the output is:

3.3
2
-1

Can someone please explain why Mathematica didn't just see every input as matching f[x_] and simply return -1?

Thanks in advance.

$\endgroup$
6
  • $\begingroup$ The order in which you issue these definitions does not matter. Mathematica will apply the "most specific" rule that matches. The finer points of that can be tricky, but here x_ is the least specific and {_?NumericQ, 0} is more specific than {_?NumericQ, _?NumericQ} because the latter contains a wildcard for the second argument whereas the first does not. $\endgroup$
    – mfvonh
    Commented Aug 27, 2014 at 18:51
  • $\begingroup$ @RunnyKine Thanks a lot for linking that answer. It has some very relevant information. @mfvonh That is what I thought, except that it seems to matter in my code whether I specify the 0 pattern first or second. Hence my confusion. $\endgroup$ Commented Aug 27, 2014 at 19:04
  • 2
    $\begingroup$ This tutorial is also relevant: The Ordering Of Definitions $\endgroup$
    – Michael E2
    Commented Aug 27, 2014 at 19:17
  • $\begingroup$ As I understand it, a pattern with a condition attached is considered more specific than one without, but in general there is no way to say that one condition test is more specific than another. How would you order x_/;blackbox1[x] and x_/;blackbox2[x]? $\endgroup$ Commented Aug 27, 2014 at 20:18
  • 1
    $\begingroup$ Also of interest: Needs["GeneralUtilities`"]; Information[GeneralUtilities`PatternOrder] $\endgroup$
    – Michael E2
    Commented Aug 27, 2014 at 21:24

0

Browse other questions tagged or ask your own question.