# Pattern matching on Orderless functions inside Hold

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?

-
I see that you have not Accepted an answer to this question. Are they all unsatisfying? Can I do anything to improve mine? –  Mr.Wizard Sep 4 '13 at 12:52
I haven't logged in to this site for a while. I've decided to accept your answer. –  Aky Sep 9 '13 at 18:21
Well, thank you. :-) –  Mr.Wizard Sep 9 '13 at 20:13

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

-

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} *)

-
+1 Very interesting. –  Aky Aug 9 '13 at 16:07

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}

-
A simpler, but related, method is to use Block[{Plus}, MatchQ[...]] as the attributes are temporarily stripped from Plus because of Block. –  rcollyer Aug 9 '13 at 13:44
+1 Definitely better than modifying the definition of a basic function –  Aky Aug 9 '13 at 16:07