Leonid wrote in chapter iv of his book : "... Module, Block and With. These constructs are explained in detail in Mathematica Book and Mathematica Help, so I will say just
As you mentioned there are many things to consider and a detailed discussion is possible. But here are some rules of thumb that I apply the majority of the time:
Module[{x}, ...]
is the safest and may be needed if either
There are existing definitions for x that you want to avoid breaking during the evaluation of the Module, or
There is existing code that relies on x being undefined (for example code like Integrate[..., x]
).
Module is also the only choice for creating and returning a new symbol. In particular, Module is sometimes needed in advanced Dynamic programming for this reason.
If you are confident there aren't important existing definitions for x or any code relying on it being undefined, then Block[{x}, ...]
is often faster. (Note that, in a project entirely coded by you, being confident of these conditions is a reasonable "encapsulation" standard that you may wish to enforce anyway, and so Block is often a sound choice in these situations.)
With[{x = ...}, expr]
is the only scoping construct that injects the value of x inside Hold[...]
. This is useful and important. With
can be either faster or slower than Block depending on expr and the particular evaluation path that is taken. With
is less flexible, however, since you can't change the definition of x inside expr.
A more practical difference between Block
and Module
can be seen here:
Module[{x}, x]
Block[{x}, x]
(*
-> x$1979
x
*)
So if you wish to return eg x
, you can use Block
. For instance,
Plot[D[Sin[x], x], {x, 0, 10}]
does not work; to make it work, one could use
Plot[Block[{x}, D[Sin[x], x]], {x, 0, 10}]
(of course this is not ideal, it is simply an example).
Another use is something like Block[{$RecursionLimit = 1000},...]
, which temporarily changes $RecursionLimit
(Module
would not have worked as it renames $RecursionLimit
).
One can also use Block
to block evaluation of something, eg
Block[{Sin}, Sin[.5]] // Trace
(*
-> {Block[{Sin},Sin[0.5]],Sin[0.5],0.479426}
*)
ie, it returns Sin[0.5]
which is only evaluated after the Block
has finished executing. This is because Sin
inside the Block
is just a symbol, rather than the sine function. You could even do something like
Block[{Sin = Cos[#/4] &}, Sin[Pi]]
(*
-> 1/Sqrt[2]
*)
(use Trace
to see how it works). So you can use Block
to locally redefine built-in functions, too:
Block[{Plus = Times}, 3 + 2]
(*
-> 6
*)
I'd like to mention the official documentation on the difference between Block
and Module
is available at http://reference.wolfram.com/mathematica/tutorial/BlocksComparedWithModules.html.
Andrew has already provided a very comprehensive answer. I would just summarize by noting that Module
is for defining local variables that can be redefined within the scope of a function definition, while With
is for defining local constants, which can't be. You also can't define a local constant based on the definition of another local constant you have set up in the same With
statement, or have multiple symbols on the LHS of a definition. That is, the following does not work.
With[{{a,b}= OptionValue /@ {opt1,opt2} }, ...]
I tend to set up complicated function definitions with Module
enclosing a With
. I set up all the local constants I can first inside the With
, e.g. the Length
of the data passed to the function, if I need that, then other local variables as needed. The reason is that With
is a little faster of you genuinely do have constants not variables.