# The replacement operator -> and :> and pattern

I'm confused by the difference between two replacement operators -> and :>, and their relation with the dummy variable (pattern). For example, the first replacement in following code gives an unexpected result.

Clear[Ei]
Ei[k_][q_] := Table[n^k, {n, 1, 4}]

Ei[2] /. {Ei[n_] -> Ei[n][q]} (* gives the unexpected {1, 4, 27, 256} *)

Ei[2] /. {Ei[n_] :> Ei[n][q]} (* gives {1, 4, 9, 16} *)

Ei[2] /. {Ei[nn_] -> Ei[nn][q]} (* gives {1, 4, 9, 16} *)

Ei[2] /. {Ei[nn_] :> Ei[nn][q]} (* gives {1, 4, 9, 16} *)


A snapshot follows,

I wonder what's going on in, for example, the 1st and the 3rd code? The 2nd and 4th seem most understandable for a human being.

• I can not reproduce this. Try using Clear["Globals*"] to be sure that no variable has an unwanted value. Apr 10, 2022 at 9:02
• @DanielHuber After quitting Mathematica and using a new notebook to run the codes, the above results remains. My Mathematica is of Mac version 12.0.0.0 Apr 10, 2022 at 9:17
• Sorry I was mistaken, I can reproduce it. The error is created when you use ->  Then the right hand side is evaluated despite n not having a value. But now comes the real bug: Ei[n][q] where n and q do not have values. This evaluates to: Table[n^k, {n, 1, 4}] what is: {1^1,2^2,3^3,4^4} Apr 10, 2022 at 9:43
• It seems to me that the only "unexpected" result is the first. If you try enclosing that calculation in Trace, you'll see that the code ends up calculating n^n in that case, hence the result. My general approach is the following: if I have a named pattern in the left hand side of a replacement rule, then I use RuleDelayed. I can't think of a case where this got me into trouble; on the other hand, using plain Rule in those cases can lead to unexpected results. Apr 10, 2022 at 11:14
• @MarcoB @Daniel Thanks for the explanation. Indeed I have always been using :> instead of ->, until my friend sent me a code with -> and things went off rail. Apr 11, 2022 at 3:19

The problem is not with -> versus :> but the way in which the variable n is treated as a local symbol in Table. As stated in the documentation, scoping in Table is akin to Block.

For example

f1[k_] := Block[{n}, Table[n^k, {n, 1, 4}]]
f2[k_] := Module[{n}, Table[n^k, {n, 1, 4}]]


is such that

{f1[n], f2[n]}


evaluates to

{{1, 4, 27, 256}, {1, 2^n, 3^n, 4^n}}

Note how the Module treats the symbol n closer to what one would expect from a local variable. For comparison

g1[k_] := Block[{n}, n^k]
g2[k_] := Module[{n}, n^k]


are such that

{g1[n], g2[n]}


evaluates to

{n^n, n\$20657^n}

See how Module will first replace n by a "local" unique symbol before evaluation whereas Block will keep n` in the "global" scope? I personally find those behaviors to be very confusing and a perennial source of really hard to find bugs.