How Modules Work

The way modules work in the Wolfram Language is basically very simple. Every time any module is used, a new symbol is created to represent each of its local variables. The new symbol is given a unique name which cannot conflict with any other names. The name is formed by taking the name you specify for the local variable, followed by $, with a unique "serial number" appended.

The serial number is found from the value of the global variable $ModuleNumber. This variable counts the total number of times any Module of any form has been used.

Module generates symbols with names of the form x$nnn to represent each local variable.

The basic principle of modules in the Wolfram Language.

This shows the symbol generated for t within the module:
Click for copyable input
The symbols are different every time any module is used:
Click for copyable input

For most purposes, you will never have to deal directly with the actual symbols generated inside modules. However, if for example you start up a dialog while a module is being executed, then you will see these symbols. The same is true whenever you use functions like Trace to watch the evaluation of modules.

You see the symbols that are generated inside modules when you use Trace:
Click for copyable input
This starts a dialog inside a module:
Click for copyable input
Inside the dialog, you see the symbols generated for local variables such as t:
Click for copyable input
You can work with these symbols as you would with any other symbols:
Click for copyable input
This returns from the dialog:
Click for copyable input

Under some circumstances, it is convenient explicitly to return symbols that are generated inside modules.

You can explicitly return symbols that are generated inside modules:
Click for copyable input
You can treat these symbols as you would any others:
Click for copyable input
Unique[x]generate a new symbol with a unique name of the form x$nnn
Unique[{x,y,}]generate a list of new symbols

Generating new symbols with unique names.

The function Unique allows you to generate new symbols in the same way as Module does. Each time you call Unique, $ModuleNumber is incremented, so that the names of new symbols are guaranteed to be unique.

This generates a unique new symbol whose name starts with x:
Click for copyable input
Each time you call Unique, you get a symbol with a larger serial number:
Click for copyable input
If you call Unique with a list of names, you get the same serial number for each of the symbols:
Click for copyable input

You can use the standard Wolfram Language ?name mechanism to get information on symbols that were generated inside modules or by the function Unique.

Executing this module generates the symbol q$nnn:
Click for copyable input
You can see the generated symbol here:
Click for copyable input

Symbols generated by Module behave in exactly the same way as other symbols for the purposes of evaluation. However, these symbols carry the attribute Temporary, which specifies that they should be removed completely from the system when they are no longer used. Thus most symbols that are generated inside modules are removed when the execution of those modules is finished. The symbols survive only if they are explicitly returned.

This shows a new q variable generated inside a module:
Click for copyable input
The new variable is removed when the execution of the module is finished, so it does not show up here:
Click for copyable input

You should realize that the use of names such as x$nnn for generated symbols is purely a convention. You can in principle give any symbol a name of this form. But if you do, the symbol may collide with one that is produced by Module.

An important point to note is that symbols generated by Module are in general unique only within a particular Wolfram Language session. The variable $ModuleNumber which determines the serial numbers for these symbols is always reset at the beginning of each session.

This means in particular that if you save expressions containing generated symbols in a file, and then read them into another session, there is no guarantee that conflicts will not occur.

One way to avoid such conflicts is explicitly to set $ModuleNumber differently at the beginning of each session. In particular, if you set $ModuleNumber=10^10 $SessionID, you should avoid any conflicts. The global variable $SessionID should give a unique number which characterizes a particular Wolfram Language session on a particular computer. The value of this variable is determined from such quantities as the absolute date and time, the ID of your computer, and, if appropriate, the ID of the particular Wolfram System process.

$ModuleNumberthe serial number for symbols generated by Module and Unique
$SessionIDa number that should be different for every Wolfram Language session

Variables to be used in determining serial numbers for generated symbols.

Having generated appropriate symbols to represent the local variables you have specified, Module[vars,body] then has to evaluate body using these symbols. The first step is to take the actual expression body as it appears inside the module, and effectively to use With to replace all occurrences of each local variable name with the appropriate generated symbol. After this is done, Module actually performs the evaluation of the resulting expression.

An important point to note is that Module[vars,body] inserts generated symbols only into the actual expression body. It does not, for example, insert such symbols into code that is called from body, but does not explicitly appear in body.

"Blocks and Local Values" discusses how you can use Block to set up "local values" which work in a different way.

Since x does not appear explicitly in the body of the module, the local value is not used:
Click for copyable input

Most of the time, you will probably set up modules by giving explicit Wolfram Language input of the form Module[vars,body]. Since the function Module has the attribute HoldAll, the form of body will usually be kept unevaluated until the module is executed.

It is, however, possible to build modules dynamically in the Wolfram Language. The generation of new symbols, and their insertion into body are always done only when a module is actually executed, not when the module is first given as Wolfram Language input.

This evaluates the body of the module immediately, making x appear explicitly:
Click for copyable input