14
MatchQ[Hold[1 + 2], Hold[2 + 1]]

returns False. But in the presence of a Blank[] in the matching pattern as in the example below

MatchQ[Hold[1 + 2], Hold[2 + _]]

which returns True, apparently the fact that Plus is Orderless is being respected.

Apart from doing something like removing the Orderless attribute from Plus, how can I make the order matter when pattern-matching in a case like this? Where can I read more about this in the documentation?

Aky
  • 2,719
  • 12
  • 19

3 Answers3

12

You need to prevent Plus being an active head in the pattern. One natural method is Block to temporarily change all appearances of Plus as suggested by rcollyer:

Block[{Plus},
  MatchQ[Hold[1 + 2], Hold[2 + _]]
]

False

For that matter you could use With as well, which replaces only explicit appearances:

With[{Plus = Null},
  MatchQ[Hold[1 + 2], Hold[2 + _]]
]

False

More directly you can make the head of [2, _] a pattern so that Plus is not active:

MatchQ[Hold[1 + 2], Hold[(h : Plus)[2, _]]]

False

h here is arbitrary.

Perhaps better is Verbatim:

MatchQ[Hold[1 + 2], Hold[Verbatim[Plus][2, _]]]

False

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
7

A quick and dirty solution to this would be to match the structure first, and the operator Plus afterwards:

MatchQ[Hold[1 + 2], Hold[f_[2, _]] /; f === Plus]
MatchQ[Hold[2 + 1], Hold[f_[2, _]] /; f === Plus]

(* {False,True} *)

jVincent
  • 14,766
  • 1
  • 42
  • 74
5

Instead of modifying the definition of such a basic function, change it temporarily. The following code

With[{Plus = tempPlus}, {MatchQ[Hold[1 + 2], Hold[2 + _]], MatchQ[Hold[1 + 2], Hold[1 + _]]}]

yields

{False, True}
Hector
  • 6,428
  • 15
  • 34
  • 7
    A simpler, but related, method is to use Block[{Plus}, MatchQ[...]] as the attributes are temporarily stripped from Plus because of Block. – rcollyer Aug 09 '13 at 13:44
  • +1 Definitely better than modifying the definition of a basic function – Aky Aug 09 '13 at 16:07