I have an expression that suggests that some expressions in a module body are dragging in definitions from outside the scope in a surprising way. First, consider a symbolic constant, y
:
ClearAll[y]
Now, define a couple of expressions that should evaluate to this constant, one immediate and one delayed:
z = y; w := y;
Let's also define a "function" v
(actually a rewrite rule in the DownValuess
of v
), that will return its argument:
v[y_] = y;
Now, the surprise is that if I define a local variable y
in a Module, various symbolic expressions involving the symbol y
, specifically w
and z
, seem to be evaluated in the environment outside the Module, where y
evaluates to itself, and other expressions involving the symbol y
, namely y
, v[y]
, and D[y^2/2, y]
seem to be evaluated in terms of the local variable. To wit:
Module[{y}, {w, v[y], y, z, D[y^2/2, y]}]
produces
{y, y$668, y$668, y, y$668}
Naturally, if I give the local variable y
a value from outside, then I don't see the secret fresh variable:
ClearAll[x];
Module[{y = x}, {w, v[y], y, z, D[y^2/2, y]}]
produces
{y, x, x, y, x}
I surmise that what's happening is that in a pre-evaluation step, any overt occurrences of y
are rewritten to the (value of the) fresh variable and then the body is evaluated. Thus, w
and z
don't get evaluated until after an equivalent to
ReplaceAll[Hold[{w, v[y], y, z, D[y^2/2, y]}], y -> y$668]
or
ReplaceAll[Hold[{w, v[y], y, z, D[y^2/2, y]}], y -> x]
is done.
Is my surmising correct?
Solve[...]
. When I refer to such symbolic expressions in various naming environments, likeModule
,Block
, andWith
, but also bodies ofFunctions
and other expressions where replacements of symbols occur, I must have total control of any possibility of "capturing" the "symbolic constants" in my symbolic expressions, lest they change meaning silently. $\endgroup$