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$

marked as duplicate by RunnyKine, mfvonh, Michael E2, Öskå, Mr.Wizard Aug 27 '14 at 22:30

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\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 Aug 27 '14 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$ – Shredderroy Aug 27 '14 at 19:04
  • 2
    $\begingroup$ This tutorial is also relevant: The Ordering Of Definitions $\endgroup$ – Michael E2 Aug 27 '14 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$ – Simon Woods Aug 27 '14 at 20:18
  • 1
    $\begingroup$ Also of interest: Needs["GeneralUtilities`"]; Information[GeneralUtilities`PatternOrder] $\endgroup$ – Michael E2 Aug 27 '14 at 21:24

Browse other questions tagged or ask your own question.