Pattern does not match with Orderless head
I am betting that this is almost certainly an optimization short-cut. If Orderless
had to try every ordering it would be extremely slow when there are a moderate number of arguments, but it is not.
Consider for example:
f @@@ Hold @@ {RandomSample[Range@12]}
Hold @@ {f @@ Range@12 /. {7 -> _}}
MatchQ[%%, %]
Hold[f[2, 6, 11, 7, 12, 10, 4, 1, 3, 5, 8, 9]] Hold[f[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, _]] False
This test is surely not performing 479,001,600 comparisons, one for each permutation. Instead I suppose that pattern matching assumes that arguments of Orderless
heads will first be placed in order and applies logic accordingly.
Since the first two of your "further examples" match I also suppose that this is because the sorted order of arguments on the RHS matches the verbatim order on the left; perhaps this case is tried first.
The following is an expansion of the explanation given by Mr.Wizard.
The pattern-matcher works on the base of the assumption that Orderless
attribute is already applied and the arguments of the Orderless
function are already sorted in the canonical order:
ClearAll[o]
SetAttributes[o, Orderless]
MatchQ[Hold[o[y, x, a]], Hold[o[_, x, a]]] (* unsorted arguments: {x, a} is NOT ordered *)
MatchQ[Hold[Evaluate@o[y, x, a]], Hold[o[_, x, a]]] (* Orderless attribute is applied *)
False True
Instead of Hold
we can use Unevaluated
with the same effect:
MatchQ[Unevaluated[o[y, x, a]], o[_, x, a]] (* {x, a} is NOT ordered *)
MatchQ[Unevaluated[o[y, a, x]], o[_, x, a]] (* {a, x} IS ordered *)
False True
Hold
and Unevaluated
prevent applying the Orderless
attribute to the arguments of the Orderless
function. They only affect the evaluation of the expression, and do not affect the pattern-matcher.
The pattern-matcher does not reorder the arguments of the Orderless
function but takes the whole expression verbatim. It assumes that the arguments are already sorted as it happens by default for evaluated function with Orderless
attribute. At the same time the pattern-matcher does sort the arguments of the pattern (with the exception of Blank
s) regardless of whether the pattern is evaluated or not. Then it compares the sorted pattern with the expression putting Blank
(s) in each position possible in the pattern.
In the light of this the Documentation statement
In matching patterns with
Orderless
functions, all possible orders of arguments are tried.
is misleading: actually only all possible positions of the Blank
s 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]]] (* {a, x} IS ordered *)
MatchQ[Hold[o[y, x, a]], Hold[o[_, x, a]]] (* {x, a} is NOT ordered *)
MatchQ[Hold[o[y, a, x]], Hold[o[x, _, a]]] (* {a, x} IS ordered *)
MatchQ[Hold[o[y, a, x]], Hold[o[x, a, _]]] (* {a, x} IS ordered *)
True False True True
In short, 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 Blank
s are indeed tried).