52
$\begingroup$

From the Mathematica documentation on Module:

Module allows you to set up local variables with names that are local to the module.

But after using Module, the symbol is created !

I understand that Module makes temporary symbols appending a number, like i$8071 and those are gone afterwards. However the symbol i is newly created, but has no value or attributes.

Here is a very simple session showing this.

Names["Global`*"]
{}

Module[{i}, Table[i^2, {i, 0, 10}]]
{0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

Names["Global`*"]
{"i"}

Attributes[i]
{}

This is not causing me any specific trouble currently, but I want to ensure that the code I'm developing is "clean" in that it doesn't pollute the Global namespace with new symbols. Could these unwanted symbols cause trouble by shadowing symbols from other packages for example? Should I just not worry about it? How can I check that my code is "clean"?

$\endgroup$
3
  • 3
    $\begingroup$ You don't even need to specify the i in the Module variable declaration, the i from the Table specification will leak out also. $\endgroup$ Commented Jul 14, 2012 at 1:25
  • $\begingroup$ I'm new to stackexchange and was unaware of how to do this. Thanks for your answers. $\endgroup$
    – owler
    Commented Jul 21, 2012 at 15:43
  • $\begingroup$ @owler thank you and I'm glad you're happy with the answer. $\endgroup$
    – Mr.Wizard
    Commented Jul 21, 2012 at 22:59

1 Answer 1

42
$\begingroup$

Symbols are created in the current context during parsing. This should not be a problem in normal circumstances as the symbols are merely "initialized" without values or properties.

See these posts for more information:


You raise good questions in the comments and I need to address them.

Shadowing

Indeed you can have problems with shadowing due to this. I intended the linked questions above to serve as examples of (and possible solutions to) this problem, but here is a short description. In a new session, if you do:

Table[x, {x, 3}];

session`x = 5;

AppendTo[$ContextPath, "session`"];

Information["x"]

Global`x

You can see that even though x was used in a localizing construct (Table) the Symbol Global`x was created. This then causes a shadowing problem if we also define session`x and hope to access it with merely x by including "session`" in the $ContextPath.

There are some alternatives to the bare form above that prevent the creation of Global`x.

Precedence of initialization

If you know you are going to use session`x you can initialize it first, and then if the context name is in $ContextPath the appearance of x in Table will be assumed to be session`x (Global`x will not be created):

session`x;
AppendTo[$ContextPath, "session`"];
Table[x, {x, 3}];
Information["x"]

session`x

Formal Symbols

You could use Formal Symbols in constructs like Table, Block, and With and Module. These symbols exist specifically to prevent conflicts of various kinds as they bear the attribute Protected and cannot accidentally have values assigned to them. (These are entered with e.g. Esc$xEsc and look much better in the Notebook than they do here.)

Table[\[FormalX], {\[FormalX], 3}];
session`x = 5;
AppendTo[$ContextPath, "session`"];
Information["x"]

session`x

x=5

Begin and End

You can use Begin and End, but as the second linked question above shows you have to be particular in their use: you must evaluate Begin on a line before the code that uses the symbols you do not want to "leak" to Global`:

Begin["session`"];

Table[x, {x, 3}];

End[];

Information["x"]

Information::notfound: Symbol x not found. >>

It cannot be rolled into a Module or other compound expression because the expression is parsed as a whole before Begin has any effect. (Workarounds do exist; see the answers to the first linked Q&A above.)

Module[{null},
  Begin["session`"];
  Table[x, {x, 3}];
  End[];
]

Information["x"]

Global`x

The mechanism of Module

You asked of this statement was correct:

Module only makes the value (and Attributes) of the symbol "local". The symbol still gets created in the current Context (Global by default), and can therefore shadow any similar name from another Context.

It is not. The creation of the Global` symbol (or as you correctly note whatever the current context is) is merely incidental to its use in Module. Module has nothing to do with it one way or the other, as it occurs during parsing, before Module even has any meaning (it is just another token at that stage).

For reference, Module works by creating a new symbol with a name based on the one you give it (x), appending $ and an incrementing number to form e.g. x$173. This symbol is then used in place of all explicit appearances of x inside the Module. This new symbol is not itself replaced with x at the end so you will see the internal form if it is returned in the output of Module, e.g. Module[{x}, x]. See this thread for a more complete description and a comparison to other scoping constructs:

What are the use cases for different scoping constructs?

$\endgroup$
8
  • 2
    $\begingroup$ Thx, but: this "inadvertent creation of symbols that I don't want to exist" means that the whole problem of "shadowing symbols from other packages" is much more likely to happen. So, I would say it could be a problem. Is this summary correct: Module only makes the value (and Attributes) of the symbol "local". The symbol still gets created in the current Context (Global by default), and can therefore shadow any similar name from another Context. $\endgroup$
    – owler
    Commented Jul 15, 2012 at 21:05
  • $\begingroup$ @owler two points: (1) You're quite right, shadowing can be a problem and I should have addressed that. (2) Your understanding of Module is not correct. I shall try to extend my answer to cover both these points later today. $\endgroup$
    – Mr.Wizard
    Commented Jul 15, 2012 at 22:32
  • $\begingroup$ @owler I have made my additions. Please review the answer and let me know if anything remains unclear. $\endgroup$
    – Mr.Wizard
    Commented Jul 15, 2012 at 23:30
  • $\begingroup$ Thx, that’s helpful, especially the bit about the parser generating the symbol. I’m used to Java (or C) where the compiler erases symbols after leaving a scope. Seems like in Mma the compiler/interpreter is always active and never forgets stuff unless you do Remove or such. I imagine this is because of the rule-rewriting nature of Mma. I clearly have a lot to learn to grok Mma. $\endgroup$
    – owler
    Commented Jul 16, 2012 at 18:31
  • 2
    $\begingroup$ Mr. Wizard, this is a very good answer. But no one ever explains why MMA is doing this. On the one hand it doesn't seem to matter if the symbols are never actually given values, but on the other hand with a big package (say) one can easily end up with thousands of such 'leaked' variables that must be taking up some memory, and which also pose some sort of security risk too, it would seem. $\endgroup$ Commented Nov 13, 2018 at 21:33

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.