5
$\begingroup$

This question already has an answer here:

Could someone clarify why the first of these MatchQ finds a match whereas the second does not? (I'm using version 10.0, in case that matters.)

MatchQ[Hold[x + 2 y], Hold[x + 2 _]]
(*True*)
MatchQ[Hold[x + 2 y + 0], Hold[x + 2 _ + 0]]
(*False*)

EDIT: The conclusion below is that when encountering an Orderless function (here Plus), the pattern matcher does not test for all possible orderings of arguments but rather sorts the pattern's constant arguments and allows blanks _ to appear in arbitrary places within that list. This reordering disregards Hold. On the other hand Hold does keep the order of the arguments of the expression fixed, so Hold[x+2y+0] is compared (with fixed argument order) to Hold[0+x+2_], Hold[0+2_+x] and Hold[2_+0+x], none of which match.

$\endgroup$

marked as duplicate by Alexey Popkov, LLlAMnYP, ubpdqn, MarcoB, user9660 Apr 12 '16 at 12:26

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.

4
$\begingroup$

UPDATE

That question is by the essence an exact duplicate of this one. The explanation given by Mr.Wizard means that the pattern-matcher is NOT capable to handle situations when an unevaluated function with Orderless attribute is wrapped by Hold. So this is indeed a gedanken functionality.

The pattern-matcher works on the base of the assumption that Orderless attribute is already applied and the arguments are sorted in the canonical order:

ClearAll[o]
SetAttributes[o, Orderless]
MatchQ[Hold[o[y, x, a]], Hold[o[_, x, a]]]
MatchQ[Hold[Evaluate@o[y, x, a]], Hold[o[_, x, a]]]
False

True

In the light of this the Documentation statement

In matching patterns with Orderless functions, all possible orders of arguments are tried.

means that actually only all possible positions of the Blanks in the pattern are tried but other arguments in the pattern are preliminarily sorted in the fixed canonical order. This is evident from the following:

MatchQ[Hold[o[y, a, x]], Hold[o[_, x, a]]]
MatchQ[Hold[o[y, x, a]], Hold[o[_, x, a]]]
MatchQ[Hold[o[y, a, x]], Hold[o[x, _, a]]]
MatchQ[Hold[o[y, a, x]], Hold[o[x, a, _]]]
True

False

True

True

In the other words, Hold prevents applying Orderless attribute in the sense that it prevents sorting of the arguments in the canonical order, but it does not prevent action of this attribute in the pattern (i.e. all possible positions of the Blanks are indeed tried).


Original answer

This behavior is definitely comes from the Orderless attribute of Plus and reproduces for arbitrary function having this attribute. As can be seen from the following, without Hold the pattern matches regardless of the order of the arguments due to Orderless attribute of o:

ClearAll[o]
SetAttributes[o, Orderless]
MatchQ[o[y, x, a], o[_, x, a]]
MatchQ[o[y, a, x], o[_, a, x]]
MatchQ[o[y, x, a], o[_, a, x]]
True

True

True

But when we wrap the expressions by Hold something breaks - now it does not match even when the order of the arguments is identical:

MatchQ[Hold[o[y, x, a]], Hold[o[_, x, a]]]
False

Surprisingly, it does match if we reorder arguments in the both expressions:

MatchQ[Hold[o[y, a, x]], Hold[o[_, a, x]]]
True

I suspect that we have a bug in the pattern matcher because this behavior cannot be explained by the documented meaning of the Orderless attribute.

$\endgroup$
3
$\begingroup$

You can put a Verbatim on the Plus:

MatchQ[Hold[x + 2 y + 0], Hold[Verbatim[Plus][x, 2 _, 0]]] (* True *)

Another way:

expr = Inactivate[x + 2 y + 1];
form = Inactivate[x + 2 _ + 1];
MatchQ[expr, IgnoringInactive@form] (* True *)
$\endgroup$
  • $\begingroup$ HoldAllComplete is an attribute, probably you mean HoldComplete. $\endgroup$ – Alexey Popkov Apr 12 '16 at 5:54
  • $\begingroup$ I know, but you can use it as a function. $\endgroup$ – M.R. Apr 12 '16 at 7:07
  • $\begingroup$ HoldAllComplete as a function works exactly as List: it does not have any Hold* attribute. $\endgroup$ – Alexey Popkov Apr 12 '16 at 7:09
  • $\begingroup$ Oh sorry, yes HoldComplete was what I meant. $\endgroup$ – M.R. Apr 12 '16 at 7:12
  • 1
    $\begingroup$ Interesting. But why does using Verbatim make the match succeed? (Or rather, why is the match failing without Verbatim?) $\endgroup$ – Bruno Le Floch Apr 12 '16 at 7:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.