5
$\begingroup$

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?

$\endgroup$
4
  • $\begingroup$ Your comment deserves several votes. post an answer! $\endgroup$ Aug 8, 2012 at 1:57
  • $\begingroup$ @Verde... Amen. $\endgroup$
    – Rojo
    Aug 8, 2012 at 2:18
  • $\begingroup$ Carefully read this answer, then read the other answers to the same question. $\endgroup$
    – Mr.Wizard
    Aug 8, 2012 at 8:50
  • $\begingroup$ @Mr.Wizard -- my "backing story" is symbolic expressions, that is, expressions wherein the symbols don't have values. For instance, the results of Solve[...]. When I refer to such symbolic expressions in various naming environments, like Module, Block, and With, but also bodies of Functions 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$
    – Reb.Cabin
    Aug 8, 2012 at 12:08

1 Answer 1

10
$\begingroup$

Module does lexical scoping. This means that whatever is explicitly passed as a parameter is applied a replacement rule with the new temporary variable, just like you suggested with your ReplaceAll snippet.

If you are looking for dynamic scoping, try Block. This means that while the evaluation of the Block is taking place, all calls to the localized symbol will not find the "external" values, but only those defined while running the Block.

Block localizes the execution, Module what`s explicitly written.

I'm sure there are a couple of good in-depth answers in the forum about Block vs Module if you do a search.

Here is a small code snippet illustrating this point:

ClearAll[z, y, w]
z = y; w := y;
v[y_] = y;

Module[{y = x}, {w, v[y], y, z, D[y^2/2, y]}]    
(* ==> {y, x, x, y, x} *)

Block[{y = x}, {w, v[y], y, z, D[y^2/2, y]}]
(* ==> {x, x, x, x, x} *)

{w, v[y], y, z, D[y^2/2, y]}
(* ==> {y, y, y, y, y} *)
$\endgroup$
5
  • $\begingroup$ Trying to understand your reply ... "whatever is explicitly passed as a parameter is replaced ...". Can you tell me what is "explicitly passed as a parameter" in the expression Module[{y}, {w, v[y], y, z, D[y^2/2, y]}]? $\endgroup$
    – Reb.Cabin
    Aug 8, 2012 at 2:30
  • 1
    $\begingroup$ @Reb.Cabin it's {w, v[y], y, z, D[y^2/2, y]} (and {y}, but I was referring to the "expression" you pass as a paramter, the second argument. If you had done expr={w, v[y], y, z, D[y^2/2, y]}; Module[{y}, expr] none would have been replaced $\endgroup$
    – Rojo
    Aug 8, 2012 at 2:32
  • 2
    $\begingroup$ One of the most clear explanations around for a never ending beginner's nightmare +1 $\endgroup$ Aug 8, 2012 at 2:33
  • $\begingroup$ Let me see if I understand you correctly. "Lexical scoping" means that the body (2d argument) of the Module is held unevaluated, then subjected to the substitutions presented in the bindings (1st argument to Module), then allowed to evaluate. "Dynamic Binding" means that current values of the variables named in the bindings (1st argument to Block) are saved, new values are assigned to the variables based on the expressions on the right-hand side of each binding evaluated in the global environment, then the body of the block is evaluated, then the variables restored from saved. Correct? $\endgroup$
    – Reb.Cabin
    Aug 8, 2012 at 5:11
  • 1
    $\begingroup$ @Reb.Cabin exactly! Functions with attribute HoldAll almost always do something to its arguments before evaluating them, just like you described with Block and Module. Also, if you want to talk about the restoring, there's also the step in which Module removes the temporary variables created if there are no references to them once the Module is over. $\endgroup$
    – Rojo
    Aug 8, 2012 at 10:03

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.