I don't really understand the behaviour of Default Argument. If I execute this command in Mathematica:
In: {f[a], f[a + b]} /. f[x_ + y_.] -> p[x, y]
Out: {p[a, 0], p[b, a]}
Why is the a and b swapped?
How can I explain the different behaviour of the above compared with the each of the following:
In: {f[a], f[a + b]} /. f[x_ + y_] -> p[x, y]
Out: {f[a], p[a, b]}
In: {f[a], f[a + b]} /. f[x_. + y_] -> p[x, y]
Out: {p[0, a], p[a, b]}
In: {f[a], f[a + b]} /. f[x_. + y_.] -> p[x, y]
Out: {p[a, 0], p[a, b]}
And similarly for:
In: {f[a], f[a b]} /. f[x_ y_.] -> p[x, y]
Out: {p[a, 1], p[b, a]}
In: {f[a], f[a b]} /. f[x_ y_] -> p[x, y]
Out: {f[a], p[a, b]}
In: {f[a], f[a b]} /. f[x_. y_] -> p[x, y]
Out: {p[1, a], p[a, b]}
In: {f[a], f[a b]} /. f[x_. y_.] -> p[x, y]
Out: {p[a, 1], p[a, b]}
From Mathematica help, what I understand is that Mathematica will return the default value if the argument of _. is not inputted. But I still cannot make the above statements any sense. Besides the obvious observable output such as reordering, I don't really understand the logic behind _. How does it relate to sum and multiplication? When will _. be useful in other than this situation?
Thanks.
Answer
Good question. I see this was largely answered in the comments yesterday, but since no one posted a formal answer I shall.
Cases 2, 3, and 4 appear relatively straightforward. (Incidentally you should be using :>, RuleDelayed here, rather than ->, to localize the pattern names x and y.) The first case that swaps positions needs a closer look however. First, observe this case:
{f[c], f[c + b]} /. f[x_. + y_.] :> p[x, y]
{p[c, 0], p[b, c]}
This is because the LHS of /. is evaluated before matching, and f[c + b] evaluates to f[b + c]. This is because of the Orderless attribute of Plus.
Considering the first case, the RHS of /. is also evaluated, and again reordering (sorting) takes place:
Trace[
{f[a], f[a + b]} /. f[x_ + y_.] :> p[x, y]
] // Column
{{{x_ + y_., y_. + x_}, f[y_. + x_]}, f[y_. + x_] :> p[x, y], f[y_. + x_] :> p[x, y]}
{f[a], f[a + b]} /. f[y_. + x_] :> p[x, y]
{p[a, 0], p[b, a]}
Here f[x_ + y_.] evaluates to f[y_. + x_]. You need to prevent the evaluation of Plus if you do not want this ordering to take place. On the left side this can be done with Unevaluated:
Unevaluated[{f[c], f[c + b]}] /. f[x_. + y_.] :> p[x, y]
{p[c, 0], p[c, b]}
It is however ineffective on the right side:
{f[a], f[a + b]} /. Unevaluated[f[x_ + y_.] :> p[x, y]]
{p[a, 0], p[b, a]}
Surprisingly, so is HoldPattern:
{f[a], f[a + b]} /. HoldPattern[f[x_ + y_.]] :> p[x, y]
{p[a, 0], p[b, a]}
I don't know why. Perhaps there is an evaluation leak within ReplaceAll that causes this to evaluate anyway, or more likely I am forgetting something about the interaction of pattern matching and the Orderless attribute.
Comments
Post a Comment