If you define a function g, like so:

g[x_?EvenQ] := "even"    
g[x_?NumberQ] := "number"

why will Mathematica always return g[2] == "Even", even though NumberQ[2] == True?

More specifically, is there a defined order in which Mathematica will try to match function cases? Does it evaluate the most specific match first?

  • $\begingroup$ g[x_NumberQ] means to match arguments with the head NumberQ. What you want is to match arguments such that NumberQ[x] is True, which is g[x_?NumberQ]. Look up PatternTest[]. (Before you make this correction, make sure to run Clear[g] first.) $\endgroup$ – J. M.'s technical difficulties Feb 27 '19 at 0:47
  • $\begingroup$ That's right---fixed. $\endgroup$ – wgoodall01 Feb 27 '19 at 0:49
  • 3
    $\begingroup$ Once you have made this fix, evaluate DownValues[g]; that should give a hint as to which case gets applied first. Generally, it tries to put special cases first before general ones. $\endgroup$ – J. M.'s technical difficulties Feb 27 '19 at 0:51
  • $\begingroup$ Or just execute ?g to see the order of the definitions. $\endgroup$ – Roman Feb 27 '19 at 2:04
  • 1
    $\begingroup$ At least closely related: How is pattern specificity decided? Ask $\endgroup$ – Kuba Jun 9 at 5:52

The Ordering Of Definitions

  • ... The Wolfram System follows the principle of trying to put more general definitions after more specific ones. This means that special cases of rules are typically tried before more general cases.
  • Although in many practical cases, the Wolfram System can recognize when one rule is more general than another, you should realize that this is not always possible. For example, if two rules both contain complicated /; conditions, it may not be possible to work out which is more general, and, in fact, there may not be a definite ordering. Whenever the appropriate ordering is not clear, the Wolfram System stores rules in the order you give them.

g[x_?EvenQ] := "even"
g[x_?NumberQ] := "number"
g /@ {1, 2}

{"number", "even"}

h[x_?NumberQ] := "number"
h[x_?EvenQ] := "even"
h /@ {1, 2}

{"number", "number"}

| improve this answer | |

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.