1
$\begingroup$

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,

enter image description here

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.

$\endgroup$
6
  • $\begingroup$ I can not reproduce this. Try using Clear["Globals*"]` to be sure that no variable has an unwanted value. $\endgroup$ Apr 10, 2022 at 9:02
  • $\begingroup$ @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 $\endgroup$
    – Lelouch
    Apr 10, 2022 at 9:17
  • 1
    $\begingroup$ 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} $\endgroup$ Apr 10, 2022 at 9:43
  • 3
    $\begingroup$ 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. $\endgroup$
    – MarcoB
    Apr 10, 2022 at 11:14
  • $\begingroup$ @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. $\endgroup$
    – Lelouch
    Apr 11, 2022 at 3:19

1 Answer 1

2
$\begingroup$

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.

$\endgroup$

Your Answer

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

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