Why does the following pattern matching not succeed?
ClearAll[f];
SetAttributes[f,Orderless];
HoldForm[f[a,d[],b,c]]/.HoldPattern[f[a,d[],b,z_]]:>{z}
(* f[a,d[],b,c] *)
I expected that because f is Orderless, the pattern matcher should try all possible orders of arguments and find a match.
If the expression is not held, I find:
ClearAll[f];
SetAttributes[f,Orderless];
f[a,d[],b,c]/.HoldPattern[f[a,d[],b,z_]]:>{z}
(* {c} *)
I.e. the desired result.
I know that because f is Orderless and the expression is evaluated, the arguments are sorted into canonical order a, b, c, d[].
It would appear in this case that the pattern matcher really does try all possible orders of arguments to find a match.
Why doesn't it work in the first example?
EDIT:
Here are some further examples:
ClearAll[f];
SetAttributes[f, Orderless];
Hold[f[a, b, c, d[]]] /. HoldPattern[f[a, b, c, z_]] :> {"Matched", {z}}
(* Hold[{"Matched", {d[]}}] *)
Hold[f[a, b, c[], d]] /. HoldPattern[f[a, b, c[], z_]] :> {"Matched", {z}}
(* Hold[{"Matched", {d}}] *)
Hold[f[a, b[], c, d]] /. HoldPattern[f[a, b[], c, z_]] :> {"Matched", {z}}
(* Hold[f[a, b[], c, d]] *)
Hold[f[a[], b, c, d]] /. HoldPattern[f[a[], b, c, z_]] :> {"Matched", {z}}
(* Hold[f[a[], b, c, d]] *)
This seems very inconsistent to me; how can I understand what is happening here?
EDIT:
An illuminating example:
Hold[f[a, c, b[], d]] /. HoldPattern[f[a, b[], c, z_]] :> {"Matched", {z}}
(* Hold[{"Matched", {d}}] *)
The Trace shows no argument reordering, but it appears that the pattern matcher must actually be reordering the pattern to (the canonical order) f[a, c, b[], z_] because f is Orderless, even though HoldPattern should prevent "regular" evaluation.
What remains confusing is what exactly is meant by "In matching patterns with Orderless functions, all possible orders of arguments are tried." in the documentation. On face value, the four examples shown above contradict this.
HoldForm[f[a, d[], c]] /. HoldPattern[f[a, d[], c_]] :> {c}outputs{c}, and if you stopffrom beingOrderlessthen the we likewise getHoldForm[f[a, d[], b, c]] /. HoldPattern[f[a, d[], b, c_]] :> {c}outputting{c}. It seems inconsistent to me. – Patrick Stevens Sep 11 '15 at 08:05Verbatimtrick works!HoldForm[f[a, d[], b, c]] /. Verbatim[f][a, d[], b, z_] :> {z}yields{c}. Although if you lose theHoldForm, it doesn't work... – march Sep 11 '15 at 15:47Verbatimworks becausefis no longer treated as a head for pattern matching purposes, and so itsOrderlessattribute has no effect. But why that attribute prevents the match in the first place is unclear :/ – bdforbes Sep 11 '15 at 22:34Verbatimdoesn't work without theHoldFormon the expression, because the arguments of the expression will be sorted into canonical form but those of the pattern will not be able to shuffle, so there is no way for the pattern to match. – bdforbes Sep 11 '15 at 22:39