8
$\begingroup$

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.

$\endgroup$
4
  • 1
    $\begingroup$ A look at the output of TracePrint[{f[a], f[a + b]} /. f[x_ + y_.] -> p[x, y]] shows that there is some reordering done; that is, x_ + y_. is automagically reordered as y_. + x_, since Plus[] is orderless, and I'm guessing Optional[] comes before Pattern[] in canonical order. $\endgroup$ May 19, 2013 at 3:16
  • $\begingroup$ @J.M. Thanks. I know it is reordered, but what is the logic behind it. Why adding _. can reorder it, why it is only the first case that a and b are reordered? $\endgroup$
    – user71346
    May 19, 2013 at 4:56
  • 1
    $\begingroup$ I did give my guess that Optional[] (y_. is internally represented as Optional[Pattern[y, Blank[]]]) comes before Pattern[] (x_ is internally represented as Pattern[x, Blank[]]) in canonical order, which is why you're seeing the reordering. But there might be a deeper explanation... $\endgroup$ May 19, 2013 at 4:58
  • 4
    $\begingroup$ Both Times[] and Plus[] are Orderless (use Attributes[] to see this), so they both sort their arguments for the purpose of having a canonical form. $\endgroup$ May 19, 2013 at 5:10

1 Answer 1

6
$\begingroup$

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.

$\endgroup$
9
  • $\begingroup$ +1. It seems that it is a bug in pattern matcher: defining HoldPattern@f[x_ + y_: 0] := p[x, y] and then evaluating f[a + b] gives p[b, a]. And with f[Unevaluated[Plus[x_, y_: 0]]] := p[x, y] we can create the definition f[x_+(y_:0)]:=p[x,y]. But it also gives p[b, a]. The same is true for definitions f[HoldPattern[Plus[x_, y_: 0]]] := p[x, y] and f[HoldPattern[Plus][x_, y_: 0]] := p[x, y]. $\endgroup$ May 20, 2013 at 10:17
  • $\begingroup$ @Alexey Is there perhaps some property of Orderless or Flat, etc., that would explain this? There are aspects of the pattern matcher that are not obvious. e.g. mathematica.stackexchange.com/a/18068/121 $\endgroup$
    – Mr.Wizard
    May 20, 2013 at 10:32
  • 3
    $\begingroup$ @AlexeyPopkov, I don't think it's a bug. HoldPattern prevents evaluation of the pattern (compare Unevaluated[Print[a + b]] /. HoldPattern@Print[y_ + x_] :> p[x, y] with and without the HoldPattern) but I don't believe it is intended to prevent the pattern matcher from respecting the Orderless attribute. Remember that ReplaceAll is just using the first of potentially multiple ways to match the pattern. If you use ReplaceList instead of ReplaceAll in the examples, the results don't seem so odd. $\endgroup$ May 20, 2013 at 11:33
  • 2
    $\begingroup$ @AlexeyPopkov I'm not sure it is possible other than blocking the attribute. Probably you shouldn't use Orderless on symbols where you care about the ordering. You could, but I don't think it's a good habit, try to make the "first thing tried" be the one you want. In this case you could do it by using {f[a], f[a + b]} /. HoldPattern[f[HoldPattern[x_] + y_.]] :> p[x, y] $\endgroup$
    – Rojo
    May 20, 2013 at 15:37
  • 1
    $\begingroup$ Optional[...] is sorted before Pattern[...], but after HoldPattern[...] $\endgroup$
    – Rojo
    May 20, 2013 at 15:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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