Read Online
Download PDF
Additional resources
Revision history
Known typos/bugs
Report a bug
License terms
About the author
"node207_1.gif" "node207_2.gif" "node207_3.gif"

4.10  Advanced topic: parameter passing and local variables

In this section we will have a brief discussion on the interplay of parameter - passing and localization of variables with scoping constructs Module, Block and With and Function, which we promised in the section on the parameter passing (4.4.7).

It turns out that the situation is very similar for all these constructs, so we will discuss the Module case only. The main question is what happens if the name of some of the formal parameters coincides with a name of one of the local variables. Let me say straight away that this is a really bad practice which should be avoided since it brings nothing except bugs into the programs. Let us consider a simple example:


Here we set up a function < fM > with conflicting names of the parameter and a local variable, and just a global variable  < a > assigned some value. Now we try a couple of inputs :




We see what happened: the value for a formal parameter < x > (5 in this case) was textually substituted in all places where the literal < x > appears on the r.h.s., before any other evaluation (and name conflict resolution in Module in particular) took place. This is in full agreement with the general  parameter - passing mechanism described earlier (section 4.4.7). But then, by the time Module actually started executing, we see what was inside - in particular, instead of the local variable initialization, we had in the variable declaration block a statement 5 = 10, which triggered an error message and resulted in Module returning unevaluated.

Conclusion: it is an error to make a name of a local variable coincide with the name of any of the function parameters.

We now try to call our function on a variable rather than a raw expression :




The results are identical, because < a > evaluated to < 5 > before the function was essentially called (recall the standard evaluation mechanism).

Next, let us see what happens when a function has a Hold attribute for the parameter in question. We modify our code accordingly :


Here, we have included additional objects to be printed - in a second you' ll see why. Now let us test :




The result here is essentially the same as before, because < 5 > is a raw object. Now let us see what happens if we call our function on a variable :



This output is quite interesting. The last output gives us a name that was internally associated with <a> in our code inside Module. It tells us that in this case, the local variable was initialized, and has shadowed the global parameter being passed.  It is instructive to see  exactly how this happened:

Step 1 :  The symbol <a> in unevaluated form (due to a Hold attribute) is textually substituted everywhere where <x> stands inside the Module (r.h.s. of the function definition). At this point we have the code:


Step 2 : A local variable < a > with a special name is initialized, and all occurrences of the symbol < a > in the code of Module are then associated with this local variable - just as if we had entered the above code from the keyboard.

Step 3: It is only at this point that the function would try to evaluate the passed parameter (since it was held unevaluated so far), but by this time all occurrences of <a> already correspond to the initialized local variable, which thus completely shadows the passed parameter value.

Step 4: The code is executed in the above form, with the results we just saw.

The conclusion is that if a given parameter is held by the function and if the passed object happened to be a global symbol with the head Symbol, then the parameter being passed is  shadowed by a local variable.

This behavior looks more mild than the one before, but in fact it is worse. Because really, colliding names in this fashion is a bad mistake in both cases, but here it may go unnoticed, since it does not result in an explicit error.

If the passed held parameter is a composite expression, Module will at least generate an error message and return unevaluated, since it is illegal to name local variables in such way) .




The final conclusions are these :

     1. There is no mystery in what happens in parameter and local variable name collisions - all the outcomes can be easily explained by the core parameter - passing mechanism based on textual substitution.
It is always an error to collide the names like this, but there are cases when this error may go unnoticed, and the parameter value be shadowed by a local variable.

A good news is that in version 6 such name collisions are usually detected and highlighted in red by the front - end.

The final comment here: this situation is not too specific to Mathematica. In C, for instance, it is also an error to name a local variable after one of the function formal parameters, and will result in an undefined behavior (at least, here it is not undefined). It is a different matter that the passed parameters themselves may serve in C as local variables, unlike in Mathematica  (see a discussion in 4.4.7).

"node207_21.gif" "node207_22.gif" "node207_23.gif"

Created by Wolfram Mathematica 6.0  (05 February 2009) Valid XHTML 1.1!