Why does ReplaceAll behave so oddly?

ReplaceAll can behave a bit oddly. Consider

(-1)^(1 + n)*Gamma[2 + n] /. {Gamma[s_] :> (s – 1)!, -((-1)^(a_)*(b_)) :> (-1)^(a + 1)*b}
(*(-1)^(1 + n) Gamma[2 + n]*)

Nothing is changed.

(-1)^(1 + n)*Gamma[2 + n] /. {Gamma[s_] :> (s – 1)!, -(-1)^(a_) :> Times[(-1)^(a + 1)]}

(*(-1)^(1 + n) (1 + n)!*)

Gamma[2 + n] is transformed into (1 + n)!.

What’s the story?



1 Answer


From the first line in the details section in the documentation for ReplaceAll:

ReplaceAll looks at each part of expr, tries all the rules on it, and then goes on to the next part of expr. The first rule that applies to a particular part is used; no further rules are tried on that part, or on any of its subparts.”

Basically what’s happening is since ReplaceAll tries all rules in a top down fashion, your

-((-1)^(a_)*(b_)) :> (-1)^(a + 1)*b

rule is applied at the very beginning, and then ReplaceAll terminates since that rule was applied to the entire expression and “The first rule that applies to a particular part is used; no further rules are tried on that part, or on any of its subparts.”

A way around this is to exploit the Flat attribute of Times, just like you did in your second line of code.

Edit: Another thing I forgot to mention is your second pattern evaluates:


(-1)^(1 + a_) b_

So really what you’re saying is

(-1)^(1 + n)*Gamma[2 + n] /. {
Gamma[s_] :> (s – 1)!, (-1)^(a_ + 1) b_ :> (-1)^(a + 1)*b

which is not what you want. So because -(-1)^x auto-evaluates to (-1)^(x+1), your second rule serves no purpose and can be removed!



I have wished for many years the detailed documentation for ReplaceAll would elaborate more precisely what “a part” is. Yes if you think you know what it does then you may think it is obvious. If you don’t think you know then you might wonder whether this is first try each atom (to use really old school LISP terminology), then every sublist, and finally the complete expression? Or in some other order? Is the order always precisely the same? I’d really like to find a reference that precisely documents this process. Thanks
– Bill
May 8 ’15 at 4:17



+1, nice explanation. I’ve yet to find a case where MMA behaves “oddly” w/r to pattern transformations – perhaps my Lisp/Term-rewriting background, but the few times I thought something odd turned out to be my blinders. @bill & @WateSoyan: When in doubt, avail yourself of MMA facilities like Trace to see under the covers. Even simpler and quite effective: Put a compound statement with a leading Print or Sow on the RHS of the rule in question…
– ciao
May 8 ’15 at 5:44



Yeah,it’s certainly a good explanation since I never know it before.Hey,guy,how could you discover it?
– WateSoyan
May 8 ’15 at 7:25



@Chip Hurst Do ReplaceRepeated and ReplaceAll behave similarly?
– WateSoyan
May 8 ’15 at 8:44



@ciao Your suggestion is useful.Since Trace can’t help in this case,Print just reflects which rule is used!
– WateSoyan
May 8 ’15 at 8:50