46

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 a few words about them here. ..."

From what I have read ( been able to find ) I am still in the dark. For packaged functions I ( simply ) use Module, because it works and I know the construct. It may not be the best choice though. It is not entirely clear to me ( from the documentation ) when, where or why to use With ( or Block ).

Question. Is there a rule of thumb / guideline on when to use Module, With or Block ( for functions in packages )? Are there limitations compared to Module? The docs say that With is faster. I want to be able to defend my =choice= for Module ( or another construct ).

Community
  • 1
  • 1
nilo de roock
  • 4,077
  • 4
  • 34
  • 62
  • 1
    Similar question on MM.SE: [What are the use cases for different scoping constructs?](http://mathematica.stackexchange.com/questions/559/what-are-the-use-cases-for-different-scoping-constructs) – E.P. Feb 17 '15 at 21:28

4 Answers4

37

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
*)
acl
  • 6,490
  • 1
  • 27
  • 33
  • Following your example I tried this. Clear[x]; x = 1; Module[{x}, x] - It returned with the ( for me ) unexpected result of x$114. – nilo de roock Jul 12 '11 at 12:30
  • 3
    The example with $RecursionLimit is very useful. – nilo de roock Jul 12 '11 at 12:31
  • 3
    Regarding your example with `Plot`. I believe `Plot` has some heuristics to decide whether to evaluate its argument *before* a numerical value is substituted for `x` or only after. The only difference your use of `Block` makes there is changing when `Plot` will evaluate its argument. It doesn't illustrate how `Block` works. You can verify this by including a `Print[x]` statement in `Plot`'s argument. (Setting the undocumented `Evaluated` option to `False` in `Plot` doesn't appear to work.) – Szabolcs Jul 12 '11 at 12:33
  • 2
    My point is that the problem with that `Plot` is evaluation of the argument. The proper way to make it work is `Plot[Evaluate[...], ...]`. The fact that wrapping the argument in `Block` also fixes it is merely accidental, and is due to `Plot`'s internal heuristics to decide about evaluation order. – Szabolcs Jul 12 '11 at 12:36
  • @Szabolcs OK, could be. I do not dispute the `Evaluate` bit, that is why I said it is not ideal the way I show it here. – acl Jul 12 '11 at 12:39
  • 1
    @Szabolcs so I tried `Plot[Block[{x}, Sow[x]; D[Sin[x], x]], {x, 0, 10}] // Reap` and `Block` does get evaluated every time. So your point is that the fact that evaluation does not occur isn't due to `Block`? I agree, but all I was trying to demonstrate is that the fact that `Block` does not rename `x` can be used in the way I showed (for cases where you can't just `Evaluate`; here it's overkill). Or did I miss your point? – acl Jul 12 '11 at 12:45
  • @acl, I was not entirely correct in my assumptions, and now I'm a bit confused. I assume that if `Plot` set a value to `x` *before* evaluating its argument, then `Block` doesn't help as we'd end up with something like `Block[{1}, D[Sin[1], 1]]`. Some weirdness about scoping rules must be at work here ... It's not at all clear to me *why* exactly this use of `Block` prevents the errors. – Szabolcs Jul 12 '11 at 12:55
  • 1
    @ndroock1 what makes this unexpected? The idea is that `Module` renames its arguments, so they are unaffected by definitions outside the `Module` body – acl Jul 12 '11 at 14:43
  • @acl. You are right. I confused myself. I thought it had touched x, but it didn't. Much is more clearer now. – nilo de roock Jul 12 '11 at 15:14
32

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

  1. There are existing definitions for x that you want to avoid breaking during the evaluation of the Module, or

  2. 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.

Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
Andrew Moylan
  • 2,893
  • 18
  • 20
  • 4
    +1 A nice summary! I have just two comments: first, if we agree that `Rule` and `RuleDelayed` are scoping constructs (which they are in some ways), they give another (non-equivalent) way of injecting inside held expressions. Second, I would *not* use `Block` for simple encapsulation, unless its dynamic scoping functionality is fully needed - it is hard to be responsible for some parts of execution stack, especially if you pass functions as parameters, where arbitrary code may be executed. Small speed improvements from using `Block` now may result in very subtle bugs later down the road. – Leonid Shifrin Jul 13 '11 at 14:11
  • 1
    That's a good point about encapsulation with Block not being safe when handling user supplied functions or expressions, since they may refer to Global` variables. In this case, Block can only be safe if it is within the private section of a package, that is, after a `Begin["\`Private\`"]` statement. – Andrew Moylan Jul 14 '11 at 01:15
  • Isn't `Unique[]` another way to create and return a new symbol? `Module[{x},x]` produces something like `$x123` whereas `Unique[]` produces something like `$234`. – Reb.Cabin Dec 15 '11 at 17:38
  • Yes Unique[] can also be used to create a new symbol. The advantage of Module[{x}...] over something like x=Unique[] is that you'll get the unique x used everywhere in e.g. Set statements like x=5. A statement like that won't work after x=Unique[]. You'd need gymnastics like Evaluate[x]=5. – Andrew Moylan Dec 15 '11 at 21:32
13

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.

Verbeia
  • 4,400
  • 2
  • 23
  • 44
  • 1
    Actually, (at least in v7) you can't define local variables in terms of the other variables in `Module` either, at least at the definition stage, i.e. `Module[{a = 1, b = a}, b]` returns `a` while `Block[{a = 1, b = a}, b]` returns 1. Since the variables are immutable in `With`, there is no way around this, but in the body of `Module` you can set `b = a` and have it behave like `Block`. – rcollyer Jul 12 '11 at 13:52
  • I tend to use `With` in places I should use `Function`, to provide variable names. I do this to ensure pure functions behave a little better, but `Function` is probably more appropriate. – rcollyer Jul 12 '11 at 13:55
  • @rcollyer: yes, I meant that I then define the local variable tha depends on the other one inside the body of `Module` and inside the enclosed `With`. Sorry if this wasn't clear. I used named constants in a `With` if I am going to use them more than once in a function definition. Otherwise pure functions are the way to go. – Verbeia Jul 12 '11 at 14:25
11

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.

Meng Lu
  • 13,726
  • 12
  • 39
  • 47