Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
1  
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. –  J. M. May 19 '13 at 3:16
    
@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? –  user71346 May 19 '13 at 4:56
1  
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... –  J. M. May 19 '13 at 4:58
4  
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. –  J. M. May 19 '13 at 5:10

1 Answer 1

up vote 6 down vote accepted

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.

share|improve this answer
    
+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]. –  Alexey Popkov May 20 '13 at 10:17
    
@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 –  Mr.Wizard May 20 '13 at 10:32
3  
@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. –  Simon Woods May 20 '13 at 11:33
2  
@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] –  Rojo May 20 '13 at 15:37
1  
Optional[...] is sorted before Pattern[...], but after HoldPattern[...] –  Rojo May 20 '13 at 15:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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