I'm trying to write a Mathematica function that will format expressions according to my preferences, for example displaying (5 c x)/Sqrt[2] as 5/Sqrt[2] c xinstead.
While attempting this I have come across some pattern matching behaviour that I don't understand, which reveals some holes in my understanding of the evaluation process.
As a simple example, consider the following:
Times[a, b, f[], c] /. Times[x__, f[], y__] :> {{x}, f[], {y}}
{{a}, f[], {b, c}}
I expected that this would output
{{a, b}, f[], {c}}
A Trace gives the following output:
Column@Trace[Times[a, b, f[], c] /. Times[x__, f[], y__] :> {{x}, f[], {y}}]
{a b f[] c,a b c f[]}{{x__ f[] y__,f[] x__ y__},f[] x__ y__:>{{x},f[],{y}},f[] x__ y__:>{{x},f[],{y}}}
a b c f[]/. f[] x__ y__:>{{x},f[],{y}}
{{a},f[],{b,c}}
Clearly Times is evaluating and shuffling its arguments to a standard form.
I will obviously have to apply HoldForm or similar, but even at this stage I don't understand why the ReplaceAll as shown in the Trace outputs this result. (EDIT: To be clear, I don't understand why or how Mathematica has gotten a b c f[] to match f[] x__ y__, or why a is matched by x__ and b, c are matched by y__).
What approach should I apply to understand why this is the result?
Next, I try again while holding expressions:
HoldForm[Times[a, b, f[], c]] /. HoldPattern[Times[x__, f[], y__]] :> {{x}, f[], {y}}
{{a},f[],{b,c}}
And I still get the undesired result.
Here is the Trace:
Trace[HoldForm[Times[a, b, f[], c]] /. HoldPattern[Times[x__, f[], y__]] :> {{x}, f[], {y}}]
{HoldPattern[x__ f[] y__]:>{{x},f[],{y}},HoldPattern[x__ f[] y__]:>{{x},f[],{y}}}a b f[] c/. HoldPattern[x__ f[] y__]:>{{x},f[],{y}}
{{a},f[],{b,c}}
Now it appears as if Times is not shuffling its arguments, but somehow along the way the b has still been matched by y__.
What is happening under the hood here?
And why is Trace not showing it?
Finally now I remembered Verbatim:
HoldForm[Times[a, b, f[], c]] /. Verbatim[Times][x__, f[], y__] :> {{x}, f[], {y}}
{{a,b},f[],{c}}
which gives the desired result.
Why does Verbatim work better here than HoldPattern?
I have been told before that Verbatim is for "escaping the pattern matcher", but the argument Times of Verbatim hardly seems like something that the pattern matcher should care about.
So to summarise:
How do I understand what is happening under the hood when pattern matching with
Times?Why did
Verbatimwork better thanHoldPattern?
EDIT:
Thinking more about this line:
HoldForm[Times[a, b, f[], c]] /. HoldPattern[Times[x__, f[], y__]] :> {{x}, f[], {y}}
I don't understand how shuffling the arguments of Times[x__, f[], y__] could cause y__ to match b c, since b and c in the expression are separated by f[].
Is the pattern matcher able to shuffle the arguments of the expression even though it is contained in HoldForm?
TimesisOrderlessand so its arguments are automatically sorted into canonical order? I still don't see whyaandb,cget matched by different blank sequences. – bdforbes Sep 11 '15 at 05:24Print[Times[a, b, f[], c] /. Times[Longest[x__], f[], y__] :> {{x}, f[], {y}}]; Print[ Times[a, b, f[], c] /. Times[Shortest[x__], f[], y__] :> {{x}, f[], {y}}]– Dr. belisarius Sep 11 '15 at 05:25Verbatimvs.HoldPatternin this case. – bdforbes Sep 11 '15 at 05:38