What are the use cases for different scoping constructs?

234

198

Mathematica includes three functions that I know of which can be used to effectively (if not actually) define a variable and give it a value within a local scope: Module, Block, and With. What are the differences between these functions (and any other scoping constructs that may exist which I don't know about), and how do I decide which one is appropriate to use in any given instance?

The documentation does describe what the different constructs do to some extent, but I feel like it's insufficiently clear on how exactly they differ from each other. Having some short examples that demonstrate the differences would be great.

David Z

Posted 2012-01-23T21:54:58.367

Reputation: 4 561

1

I find the documentation for Module, Block and With to be quite confusing, but the tutorials How Modules Work, Blocks and Local Values and Local Constants are a much nicer introduction and much more straightforward than the documentation.

– Emilio Pisanty – 2014-02-13T10:18:49.963

5

Older question on SO: Mathematica Module versus With or Block - Guideline, rule of thumb for usage?

– Emilio Pisanty – 2015-02-17T21:29:04.343

Related: "Plot using With versus Plot using Block."

– Alexey Popkov – 2016-08-22T18:24:23.210

Cross-posted on WC: "Scoping constructs in Wolfram Language."

– Alexey Popkov – 2017-02-24T08:40:49.043

Answers

232

You will find a lot of information in this answer. I will add a few personal notes.

Module

Use Module when you want to localize variables inside your function's body, and those variables will potentially acquire and/or change their values during the computation.

Basic use

For example:

f[x_]:=Module[{y=x^2},y=y+x;{x,y}]

Here, a local mutable variable (symbol) y is local to the Module, and is, indeed, a symbol with a unique name. This is the closest you have in Mathematica to, say, local variables in C.

Advanced uses

Module also has advanced uses. One of them is to create closures - functions with a persistent state. My third post in this thread illustrates many cases of that and has further references. One example I will steal from there: the following function will produce the next Fibonacci number on demand, and yet it will be as fast as the iterative loop implementation for generation of consecutive Fibonacci numbers (since Module is invoked only once, when the function is defined):

Module[{prev, prevprev, this}, 
   reset[] := (prev = 1; prevprev = 1); 
   reset[]; 
   nextFib[] := (this = prev + prevprev; prevprev = prev; prev = this)
];

 
reset[]; 
Table[nextFib[], {1000}]; // Timing 

(* 
  ---> {0.01, Null} 
*)

One problem with persistence created with Module-variables is that one should not generally serialize such state (definitions), for example by saving the state via Save or DumpSave. This is because, the uniqueness of names for Module-generated symbols is guaranteed only within a single Mathematica session.

Module also allows one to create local functions, which With does not (except pure functions). This is a very powerful capability. It is particularly useful for writing recursive functions, but not only. In the link mentioned above, there were examples of this. One problem with local functions created by Module is that these symbols won't be automatically garbage-collected when Module finishes (if they have DownValues, SubValues or UpValues. OwnValues are fine), and so may lead to memory leaks. To avoid that, one can Clear these symbols inside Module before returning the result.

With

Use With to define local constants, which can not be changed inside the body of your function.

Basic use

For example,

f[x_,y_]:=With[{sum = x+y},{sum *x, sum *y}]

It is instructive to trace the execution of f. You will notice that sum gets replaced by its value very early on, before the body starts evaluating. This is quite unlike Module, where variable entries get replaced by their values in the process of evaluation, just as it would normally happen were the variables global.

Advanced uses

On an advanced level, With can be used to inject some evaluated code deep into some expression which is otherwise unevaluated:

With[{x=5},Hold[Hold[x^2]]]

(*
    Hold[Hold[5^2]]
*)

and is thus an important meta-programming tool. There are lots of uses for this feature, in particular one can use this to inject code into Compile at run-time right before compilation. This can extend the capabilities / flexibility of Compile quite a bit. One example can be found in my answer to this question.

The semantics of With is similar to that of rule substitutions, but an important difference is that With cares about inner scoping constructs (during variable name collisions), while rules don't. Both behaviors can be useful in different situations.

Module vs With

Both of these are lexical scoping constructs, which means that they bind their variables to lexical their occurrences in the code. Technically, the major difference between them is that you can not change the values of constants initialized in With, in the body of With, while you can change values of Module variables inside the body. On a deeper level, this is because With does not generate any new symbols. It does all the replacements before the body evaluates, and by that time no "constant symbols" are at all present, all of them replaced with their values. Module, OTOH, does generate temporary symbols (which are normal symbols with an attribute Temporary), which can store a mutable state.

Stylistically, it is better to use With if you know that your variables are in fact constants, i.e. they won't change during the code execution. Since With does not create extra (mutable) state, the code is cleaner. Also, you have more chances to catch an occasional erroneous attempt in the code to modify such a constant.

Performance-wise, With tends to be faster than Module, because it does not have to create new variables and then destroy them. This however usually only shows up for very light-weight functions. I would not base my preference of one over another on performance boosts.

Block

Basic use

Block localizes the value of the variable. In this example, a does not refer to i literally inside Block, but still uses the value set by Block.

a:=i
Block[{i=2},a]
{a,i}

Block therefore affects the evaluation stack, not just the literal occurrences of a symbol inside the code of its body. Its effects are much less local than those of lexical scoping constructs, which makes it much harder to debug programs which use Block extensively. It is not much different from using global variables, except that Blockguarantees that their values will be restored to their previous values once the execution exits Block (which is often a big deal). Even so, this non-transparent and non-local manipulation of the variable values is one reason to avoid using Block where With and / or Module can be used. But there are more (see below).

In practice, my advice would be to avoid using Block unless you know quite well why you need it. It is more error-prone to use it for variable localization than With or Module, because it does not prevent variable name collisions, and those will be quite hard to debug. One of the reasons people suggest to use Block is that they claim it is faster. While it is true, my opinion is that the speed advantage is minimal while the risk is high. I elaborated on this point here, where at the bottom there is also an idiom which allows one to have the best of both worlds. In addition to these reasons, as noted by @Albert Retey, using Block with the Dynamic - related functionality may lead to nasty surprises, and errors resulting from that may also be quite non-local and hard to find.

One valid use of Block is to temporarily redefine some global system settings / variables. One of the most common such use cases is when we want to temporarily change the value of $RecursionLimit or $IterationLimit variables. Note however that while using Block[{$IterationLimit = Infinity}, ...] is generally okay, using Block[{$RecursionLimit = Infinity}, ...] is not, since the stack space is limited and if it gets exhausted, the kernel will crash. A detailed discussion of this topic and how to make functions tail-recursive in Mathematica, can be found e.g. in my answer to this question.

It is quite interesting that the same ability of Block can be used to significantly extend the control the user has over namespaces/symbol encapsulation. For example, if you want to load a package, but not add its context to the $ContextPath (may be, to avoid shadowing problems), all you have to do is

Block[{$ContextPath}, Needs[Your-package]]

As another example, some package you want to load modifies some other function (say, System`SomeFunction), and you want to prevent that without changing the code of the package. Then, you use something like

Block[{SomeFunction}, Needs[That-package]]

which ensures that all those modifications did not affect actual definitions for SomeFunction - see this answer for an example of this.

Advanced uses

Block is a very powerful metaprogramming device, because you can make every symbol (including system functions) temporarily "forget" what it is (its definitions and other global properties), and this may allow one to change the order of evaluation of an expression involving that symbol(s) in non-trivial ways, which may be hard to achieve by other means of evaluation control (this won't work on Locked symbols). There are many examples of this at work, one which comes to mind now is the LetL macro from my answer to this question.

Another more advanced use of Block is to ensure that all used variables would be restored to their initial values, even in the case of Abort or exception happening somewhere inside the body of Block. In other words, it can be used to ensure that the system will not find itself in an illegal state in the case of sudden failure. If you wrap your critical (global) variables in Block, it will guarantee you this.

A related use of Block is when we want to be sure that some symbols will be cleared at the end. This question and answers there represent good examples of using Block for this purpose.

Variable name conflicts

In nested scoping constructs, it may happen that they define variables with the same names. Such conflicts are typically resolved in favor of the inner scoping construct. The documentation contains more details.

Block vs Module/With

So, Block implements dynamic scoping, meaning that it binds variables in time rather than in space. One can say that a variable localized by Block will have its value during the time this Block executes (unless further redefined inside of it, of course). I tried to outline the differences between Block and With/Module (dynamic vs lexical scoping) in this answer.

Some conclusions

  • For most common purposes of variable localization, use Module
  • For local constants, use With
  • Do not ordinarily use Block for introducing local variables
  • All of the scoping constructs under discussion have advanced uses. For Module this is mostly creating and encapsulating non-trivial state (persistent or not). For With, this is mostly injecting inside unevaluated expressions. For Block, there are several advanced uses, but all of them are, well, advanced. I'd be worried if I found myself using Block a lot, but there are cases when it is indispensable.

Leonid Shifrin

Posted 2012-01-23T21:54:58.367

Reputation: 108 027

1very clear. well-deserved +1 – acl – 2012-01-23T23:36:38.040

3@acl Thanks! I knew there will be many answers, but just could not resist:). I actually consider two of my strongest mma areas to be scoping and performance-tuning, so whenever there is a discussion on those, I go out of control, as you correctly noted some few days ago :) – Leonid Shifrin – 2012-01-23T23:40:40.690

You mentioned that Module-locale symbols with DownValues don't get garbage collected, which sounded worrying, so I tried Module[{a}, a[1] = 1; ] in a fresh kernel. In this case a (or rather its renamed version) does get garbage collected. Can you elaborate? – Szabolcs – 2012-01-24T00:00:56.660

@Szabolcs You need to refer to such function by some global object first, which you can later Remove - it is in such cases that we get into trouble. For example: ClearAll[f];Module[{a}, a[1] = 1; f[x_] := a[x]];Remove[f]. Even though we later removed f, the local a was not collected. Clearing $HistoryLenth does not seem to help. I was actually bitten by this quite seriously a few times, when I worked in an OO fashion and abandoned lots of such objects. So, I ended up with modified Module where I could clean up manually later. – Leonid Shifrin – 2012-01-24T00:06:21.533

I got it now. I can also reproduce by playing with Temporary. It is an interesting (non-obvious) observation you make that Clear[a] will allow a to get garbage collected. I'll add that ClearAll will not (because it removes the Temporary attribute). Can you edit your post and change ClearAll to Clear? – Szabolcs – 2012-01-24T00:13:18.497

@Szabolcs To put it differently: collection is only attempted just before we leave Module. Because the local function was still referenced by a global symbol at that point, it could not be collected then. And it turns out that in such cases, it gets the "rights" of a global object - it becomes a global object. Even though it still has a Temporary attribute, it will never be automatically collected, regardless of what happens to the symbols which were referencing it. – Leonid Shifrin – 2012-01-24T00:14:11.960

To make it more clear, Module[{a}, ClearAll[a] ] will prevent the renamed version of a from being removed. Try it in a fresh kernel then do ?Global`* – Szabolcs – 2012-01-24T00:15:20.040

@Szabolcs Now you've made a good observation, thanks! I actually recall that I got that at some point when was experimenting with it (when it mattered), but forgot about Clear / ClearAll subtlety since then (it has been 3 years or something). This is because I actually started doing things differently, frequently even using Remove instead. I will surely edit. – Leonid Shifrin – 2012-01-24T00:17:11.613

A small correction to this comment: "Even though it still has a Temporary attribute, it will never be automatically collected, regardless of what happens to the symbols which were referencing it." It's probably better not to stress never. In a simple test, it does get garbage collected if it is not referenced any more and its downvalues are removed. I did $HistoryLength = 0; Module[{a}, a[]=1; f=a; name = SymbolName[a]]; Clear[f]; With[{s = name}, Clear[s]] The renamed a gets garbage collected only at the very last step. – Szabolcs – 2012-01-24T00:22:55.160

@Szabolcs Yes, of course, I said never meaning that it preserves its content. I meant that it does not depend now on which symbols were originally referencing it. I mentioned the presence of one of the ...Values (except OwnValues) as a preresuisite for this behavior. – Leonid Shifrin – 2012-01-24T00:26:34.577

Let's get some rest, it's way too late :-) (2:30 here) – Szabolcs – 2012-01-24T00:27:29.707

@Szabolcs I wanted to suggest the same :) 4:30 here, and I must bring my kid to the kindergarden at 9... Good night! – Leonid Shifrin – 2012-01-24T00:29:09.393

@LeonidShifrin, well sumarized. Two additions: Block[{$RecusionLeverl=}] type of thinks and Performance for Block is very good since no new symbols need to be created. – None – 2012-01-24T08:26:17.500

@ruebenko Thanks. I mentioned that Block is faster, but I also mentioned that, except possibly in packages, this speed boost comes at a risk of name collisions, so I personally tend to avoid it for such purposes. I actually linked to the SO question where the speed comparison is elaborated. As to your first point - perhaps I should have mentioned this use case, but I noticed after posting that it was mentioned in other answers. Do you think it would still be better to include it here? Also, there is a bunch of other more subtle things that I left out here. – Leonid Shifrin – 2012-01-24T09:51:06.847

@LeonidShifrin, I think is would be useful to include, since this comes up again and again, it would be good to have a reference that is complete, kind of a wiki. If you don't mind the work. – None – 2012-01-24T10:25:06.713

@ruebenko I don't mind the work :) Will include, and also think of a few other important cases and / or subtleties. – Leonid Shifrin – 2012-01-24T10:27:00.440

@LeonidShifrin, I don't know, I somehow did have that impression ;-) – None – 2012-01-24T10:36:06.290

When discussing lexical scoping you make this statement: "they bind their variables to lexical their occurrences in the code" which doesn't make sense to me. Could you elaborate? – rcollyer – 2012-01-24T14:14:56.790

2I think this if fairly complete, I just would like to mention another example why Block is dangerous: It can incidentally trigger Dynamic evaluations -- and in extreme cases hang or crash the FrontEnd. Evaluate this to see why: Dynamic[x] and then in another cell this: Block[{x},x=1;Pause[1]] – Albert Retey – 2012-01-24T14:25:17.053

@Albert Thanks, your opinion is valuable to me. B.t.w., I did evaluate your example, but nothing bad happened (Win7, 64 bit, M8.0.0). I probably missed something. What was supposed to happen? – Leonid Shifrin – 2012-01-24T15:33:38.033

@rcollyer Sorry, I somehow missed your comment. I think I was too tired yesterday. I meant something like "bind the variables in all places where they are literally present in the body, but not say in the code called when body evaluates". – Leonid Shifrin – 2012-01-24T18:41:26.380

@LeonidShifrin: In that simple case nothing bad happens, it just shows that while you might think that the localized x will be harmless, it will actually trigger the dynamic. Nothing too surprising when seen in this simple case, but very bad if you imagine a more complex setup. Think of a couple of such Dynamics and e.g. a Map[f,Range[10000]] where f uses such a block and the Dynamics that seems unrelated go havoc. I have crashed the FrontEnd that way and it was very hard to find that error. Of course I should have used other means to localize -- but that's what the comment was all about :-) – Albert Retey – 2012-01-24T23:49:06.177

2Another comment on the Dynamic example, maybe a little off topic: Would anyone except for me condider it as a bug that the Dynamic[x] will keep showing 1 even after Block[{x},x=1;Pause[1]] has finished and a shift-return-evaluation will show that x has no value defined anymore? Using a Clear[x] will make it update... – Albert Retey – 2012-01-24T23:51:45.923

@Albert I see now. Edited, please see if it's ok. Quite frankly, while Dynamic is a cool concept and I've used it a lot, I think it goes a bit against the design ideology behind Mathematica, part of which is to expose to the user enough internals to make things intuitive and understandable at the core. To put it differently, while I'd use it for prototyping, I'd probably resort to other means (Java Swing, or web interface and Javascript) if I had to make UI-s for production to be used by others - just because I can not be sure how it will behave in this or that case. May be it's just me. – Leonid Shifrin – 2012-01-25T17:17:28.860

@LeonidShifrin: I agree that the Dynamic functionality has its drawbacks and limits. But one can do more than I first thought when being careful. We use it to create even relatively complex guis for customers that run them in PlayerPro. Unfortunately you can't use any of the alternatives when it's supposed to run with PlayerPro. As for your edit, it expresses exactly what I meant -- no complaints (and it even mentions me :-) – Albert Retey – 2012-01-25T20:50:56.707

When I first learned of With, I had original thought it wouldn't create new symbols (which is also what you say). But running With[{i = 2}, f[x_] := i*x] followed by Names["Global`*"] in a fresh kernel yields {"f", "i", "x", "x$"}, indicating that on the contrary the symbol i is created (version 10.2). Any idea of what's going on? – QuantumDot – 2015-10-05T21:10:16.160

@QuantumDot The symbol i is created not by With, but by the FrontEnd parser, because the code is parsed long before With has any chance to fire, and symbols are created during parsing (symbols are also created by Module and Unique, of course, but not by With or Block). This is another reason why it is a good idea to place all implementation in "`Private`" sub-context of the package - since then all such symbols are created in the private section of the package. – Leonid Shifrin – 2015-10-05T21:14:49.273

"One problem with local functions created by Module is that these symbols won't be automatically garbage-collected when Module finishes (if they have DownValues...)" Maybe this is changed in recent versions of Mathematica? – unlikely – 2016-03-16T07:52:04.163

@unlikely I don't think so. Check the nested Module example from this post, it illustrates exactly this issue, and the problem still exists. It may well be that this issue is unsolvable within the currently existing model of lexical scoping in Mathematica - although this I can't tell for sure.

– Leonid Shifrin – 2016-03-16T15:39:07.967

@LeonidShifrin This apply to "complex" situation like the example? In a simple case like Module[{f}, f[x_] := x^2] without cross-references, is the f garbage collected despite having DownValues? Or does I need to Clear[f] or do something else before leaving Module to avoid leaks? – unlikely – 2016-03-16T15:55:59.997

@unlikely In the simple case you considered, garbage collection works all right. The problem happens only when the local symbol (f in your case) with DownValues (or SubValues, UpValues) is referenced by something more global, at the time when such definition is made. In the example from that link, it was referenced by a variable local by the enclosing scope. Note that even though that variable was later garbage-collected, this didn't help the inner variable. – Leonid Shifrin – 2016-03-16T16:03:38.570

@LeonidShifrin Thanks, I can now clean some of my code removing unecessary Clear... :) – unlikely – 2016-03-16T17:37:39.533

@unlikely Was glad to help. – Leonid Shifrin – 2016-03-16T18:28:11.593

Hello again; I've been studying your "advanced" use of Module to create closures; but I'm not fully understanding it. I thought the key point/advantage here is that the variables prev, prevprev, this are totally inaccessible except by using reset[] or nextFib[]. However, this is not completely true since they still appear in the Global` context as prev$317, prevprev$317, etc (the 317=$ModuleNumber), and I can even corrupt the functions by modifying e.g. prev$317 = 0.133. Could you clarify the advantage of this use case over just having the code outside Module? – QuantumDot – 2017-08-01T21:54:52.033

@QuantumDot You can't make variables fully inaccessible in Mathematica, for reasons I have outlined here. So, yes, this is a fundamental limitation. However, normally one would not come up with such variables as what Module is producing. Closures are most useful because they can access the variables from surrounding environment. The fact that in Mathematica, the user can (with some effort) also access those variables, does not make closures less useful - it makes the lexical scoping less robust, but there isn't much one can do about this.

– Leonid Shifrin – 2017-08-01T22:01:00.703

93

The differences between Module, Block and With are nicely summarized by the results of the following expressions:

x = "global"; f[] := x

Module[{x = "local"}, {x, f[], Hold[x]}]
 Block[{x = "local"}, {x, f[], Hold[x]}]
  With[{x = "local"}, {x, f[], Hold[x]}]

which returns:

{"local", "global", Hold[x$123]}        (* Module *)
{"local", "local",  Hold[x]}            (* Block *)
{"local", "global", Hold["local"]}      (* With *)

Executive Summary

Module: the work-horse of scoping constructs -- use it unless you have special needs

Block: use it when you need to temporarily change the definition of an existing symbol

With: use it when you need to insert values into held expressions

More details follow...

Module

Module evaluates its second argument after replacing all of the "local symbols" (x in this case) with freshly generated unique temporary symbols. Thus,

Module[{x = "local"}, {x, f[], Hold[x]}]

is roughly equivalent to:

x$123 = "local"; {x$123, f[], Hold[x$123]}

yielding the result:

{"local", "global", Hold[x$123]}

Block

Block does not generate "local" symbols. Instead, temporarily it clears all of the definitions and attributes associated with the supplied symbols, evaluates the second argument, and then restores the cleared definitions. Thus:

Block[{x = "local"}, {x, f[], Hold[x]}]

is roughly equivalent to:

ClearAll[x]; x = "local"; {x, f[], Hold[x]} /. r_ :> (x = "global"; r)

with the result:

{"local", "local",  Hold[x]}

In practice, the clearing and restoration of the symbol x is done more efficiently by the Mathematica kernel. Take careful note that f[] evaluates to "local". The global definition of x is changed for the duration of the evaluation of the Block expression. This behaviour can be very surprising, so be sure that this is your intent before using Block.

With

With replaces all occurrences of the listed symbols in the second argument with the corresponding values, and then evaluates the result. Thus:

With[{x = "local"}, {x, f[], Hold[x]}]

is equivalent to:

{"local", f[], Hold["local"]}

with the result:

{"local", "global", Hold["local"]}

Note especially that With differs from the other two constructs in that it can change the contents of held expressions.

Undocumented Goodies

Internal`InheritedBlock acts like Block, except that it does not clear the existing definition first. This is extremely useful if you want to temporarily augment the functionality of an existing symbol instead of temporarily replacing it. I wish this were not "internal".

Due to an implementation coincidence, Block (but not With or Module) can be used as a nifty trick to force evaluation on the right hand side of a rule, e.g.

Hold[{2, 3}] /. n_Integer :> Block[{}, n*n /; True]

With can be used in a similar fashion, if more verbose:

Hold[{2, 3}] /. n_Integer :> With[{r = n*n}, r /; True]

WReach

Posted 2012-01-23T21:54:58.367

Reputation: 62 787

Are the brackets on f necessary? You could do the same with y:=x. – Emilio Pisanty – 2015-04-20T11:55:32.620

3@episanty The brackets are not strictly necessary but, following common convention, their presence gives the reader a clue that f is a potentially non-determinstic computation rather than a simple value. – WReach – 2015-04-20T14:27:57.433

The last bit, forcing evaluation on the rhs of a rule, is interesting. There isn't much wiggle room, if any. The condition must be inside the block expression, not outside, so the documentation of Condition is little help understanding the trick. It must be RuleDelayed and not Rule, which is a bit easier to understand; you want the trick evaluated after substitution, not before. So it looks like you're getting a RuleDelayed that's going to eval a Condition; the Block incidentally forces one more round of evaluation before the test of the Condition -- something along these lines. – Reb.Cabin – 2012-08-08T13:02:40.453

@Reb.Cabin Trace will reveal the "implementation coincidence" that these expressions invoke RuleCondition in a manner useful to this context. See also the brief discussion here.

– WReach – 2012-08-08T13:36:26.827

41

I'll cover a few typical uses of Block, neither of which is possible using Module or With.

Temporarily removing definitions

When you do

Block[ {a = x}, ... ]

the original definition of a is effectively replaced by whatever new definition is given in the first argument of Block, for the duration of the evaluation of Block only. If we give no definition, Block temporarily "undefines" whatever was passed to it as first argument. This works even for built-ins:

Block[ {Print}, Print["boo!"]; ]

prints nothing.

Temporarily redefining symbols

Block is also commonly used to temporarily change the value of system variables. Take for example this simple recursive implementation of a list maximum function:

max[{a_}] := a
max[list_List] := 
 With[{m = max@Rest[list]}, If[First[list] > m, First[list], m]]

For a long list it fails because the value of $RecursionLimit is too low. But we can increase $RecursionLimit only temporarily using Block:

Block[{$RecursionLimit = 1000}, max[RandomInteger[10000, 300]]]

Implementing functions that localize their arguments

Functions like Table, Sum, Plot, FindRoot, NIntegrate, etc. use Block to localize their variable.

Here's a possible implementation of a table function which works like Table:

Clear[table]
SetAttributes[table, HoldAll]
table[expr_, {x_, min_, max_, step_}] :=
 Block[{x},
  x = min;
  Reap[While[x <= max,
     Sow[expr];
     x += step
     ]][[2, 1]]
  ]

We can use it just like Table:

table[i, {i, 1, 100, 4}]

(*
 ==> {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, \
      61, 65, 69, 73, 77, 81, 85, 89, 93, 97}
*)

Using Block made sure that this function will work even if i has a value globally.


Internal`InheritedBlock

Here it's also worth mentioning Internal`InheritedBlock. Like with Block, any changes made to the local symbols of InheritedBlock are lost when it finishes evaluating. However, unlike Block, it keeps the original definition of the localized symbols too.

This is useful for modifying existing (or built-in) functions temporarily. Here's an example to illustrate:

Print does not have the HoldAll attribute:

Print[1 + 1]

(* ==> 2 *)

We can assign HoldAll to Print temporarily:

Internal`InheritedBlock[
 {Print},
 SetAttributes[Print, HoldAll];
 Print[1 + 1];
]

(* ==> 1+1 *)

As soon as InheritedBlock exits, this behaviour is reverted:

Print[1 + 1]

(* ==> 2 *)

Szabolcs

Posted 2012-01-23T21:54:58.367

Reputation: 213 047

I too tend to use Block[] whenever I have to temporarily redefine system variables like $IterationLimit. Nice. :) – J. M.'s ennui – 2012-01-24T08:41:53.200

@szabolcs In the last line of the text in the answer above, shouldn't the word exits be used instead of exists? (i.e. "As soon as InheritedBlock exits ...") – TransferOrbit – 2015-03-05T09:13:54.653

@zentient Thanks, corrected. – Szabolcs – 2015-03-05T13:28:46.317

27

There will no doubt be plenty of answers for this one. However the short answer is:

  • Use With for local constants that you don't have to change subsequently.
  • Use Module for local variables that are local to that piece of code.
  • Use Block for local variables that are local to that sequence of evaluation.

This tutorial in the Mathematica documentation discusses the difference between Block and Module in more depth. The essential difference is that Block substitutes in the local value of the variable even if the piece of code is calling some other function that was defined outside that Block statement, and that uses the same variable name.

In my view, With is the least well understood. It is marginally faster for cases where what you have is really a constant, e.g. an intermediate calcuation in a larger function definition. For example, consider a function that returns the contribution of each element to the total, the average value of each element and the sum of squares normalized by the length of the list. The intermediate values of the length and total of the list don't subsequently change, so you can use With rather than Module.

f[x_List]:= With[{n=Length[x],t=Total[x]}, 
   {x/t, t/n, Total[x^2]/n}  ]

Other times, it is easier to use Module even if the local entity is a constant (i.e. not redefined), because it builds on other local variables. Consider:

ff[x_List]:= Module[{n=Length[x],t=Total[x],ssqs}, 
  ssqs = Total[x^2]/n;
   {x/t, t/n, ssqs} ]

Verbeia

Posted 2012-01-23T21:54:58.367

Reputation: 33 191

1Sorry for the late comment, I just noticed the additional answers here. An added point with With, you can use SetDelayed, which increases its usefulness. – rcollyer – 2012-05-01T15:33:06.740

1Yet another scoping construct that I didn't see mentioned is DynamicModule. – Ted Ersek – 2013-01-31T01:25:45.693

23

I will leave the explanation of the difference between lexical and dynamic to those more qualified than myself (and to the documentation). One practical difference between Block and Module is this:

Module[{x}, x]
Block[{x}, x]
(*
-> x$1979
   x
*)

That is, if you construct something inside a Block with a blocked variable and then return it, you may use it. Thus, you may do

Block[{Sin = Cos[#/4] &}, Sin[Pi]]
(*
-> 1/Sqrt[2]
*)

More usefully, you can do things like Block[{$RecursionLimit = 1000},...], which temporarily changes $RecursionLimit (Module would not have worked as it renames $RecursionLimit).

With[{x=5},expr] is slightly different. First, the value of x is literally inserted wherever x appears in expr, even in held expressions:

Block[{x = 5}, Hold[x]]
Module[{x = 5}, Hold[x]]
With[{x = 5}, Hold[x]]
(*
Hold[x]
Hold[x$2413]
Hold[5]
*)

Consequently, you cannot assign anything to x inside expr: try

With[{x = 5}, x = Sin[42]] // Trace
Block[{x = 5}, x = Sin[42]; Print[x]] // Trace
Module[{x = 5}, x = Sin[42]; Print[x]] // Trace
(*
{With[{x=5},x=Sin[42]],5=Sin[42] (*lots of errors*)}

Sin[42]

{Block[{x=5},x=Sin[42];Print[x]],{x=5,5},{x=Sin[42];Print[x],{x=Sin[42],Sin[42]},
{{x,Sin[42]},Print[Sin[42]],{MakeBoxes[Sin[42],StandardForm],RowBox[{Sin,
[,42,]}]},Null},Null},Null}


Sin[42]

{Module[{x=5},x=Sin[42];Print[x]],{x$847=5,5},{x$847=Sin[42];Print[x$847],
{x$847=Sin[42],Sin[42]},{{x$847,Sin[42]},Print[Sin[42]],
{MakeBoxes[Sin[42],StandardForm],RowBox[{Sin,[,42,]}]},Null},Null},Null}


*)

so you can see that With literally replaces x by Sin[42] in the body and then evaluates it, while Block and Module do not.

acl

Posted 2012-01-23T21:54:58.367

Reputation: 19 146

15

With allows definition of local constants. An example (that I recently posted as an answer) would have been a good candidate for this: a regular expresion.

With[{regex = RegularExpression[...]},
    If[... something with regex ...];
    If[... something else with regex ...]
]

Other uses would be if you need to precalculate a local constant (Sin[20°] etc) to save processing time when the value is needed more than once.


Block and Module seem like two things for the same purpose on first sight: scoping. However, the way they assign the variables is different: Module replaces only explicit appearances of variables, while Block also takes into account implicit ones.

Here's an example of that (taken from the Mathematica documentation):

m = i^2
i^2
Block[{i = a}, i + m]
a + a^2
Module[{i = a}, i + m]
a + i^2

And why all this?

The thing is again how Mathematica stores variables: a=1 does not assign the value 1 to a - it creates a pattern defining that every time a appears in the code, it is to be replaced by 1. In the sense of programming, this means that Mathematically dynamically changes its own code throughout the evaluation. The difference from this behavior to normal programming languages is why there's Block and Module. Module takes a snapshot of the code inside and starts evaluating it, replacing explicit occurences of the local variables; Block really does the replacement, and then starts going through the code. Memory hook: *B*lock comes before *M*odule in the alphabet, so it does the replacement first, and then starts evaluating.

David

Posted 2012-01-23T21:54:58.367

Reputation: 14 421

1I am not sure about "Block really does the replacement, and then starts going through the code", as for instance Block[{x = a}, Hold[x]] returns Hold[x]. – acl – 2012-01-23T22:36:10.973

... that is correct. Can we settle on a "for practical purposes"? :-) – David – 2012-01-23T22:41:26.460

But I think that for practical purposes this is really the distinction between With and Block ("this"=whether it's better to think of it as literal replacement or a scoping construct). But what do I know :) – acl – 2012-01-23T22:45:38.163

14

The difference is demonstrated by the following code snippet, where I've changed only the scoping construct. But let's first define a simple function:

f[x_]:=x+a

Now we first look at Block:

Block[{a=b}, Print[a]; a=3; f[x]+a]+foo[a,b]
(*
Prints: b
--> 6 + x + foo[a, b]
*)

As you see, the global value of a is temporarily assigned to b, then inside changed to 3. That is, not only the a inside the Block, but also the value of a in the function call from the Block is modified. Outside the block, the change is undone, including any change done inside the block (the a=3).

Let's now look at Module:

Module[{a=b}, Print[a]; a=3; f[x]+a]+foo[a,b]
(*
Prints: b
--> 3 + a + x + foo[a, b]
*)

As you see, this time the a in the function does not evaluate to b. Indeed, the a inside the Module is replaced by a temporary variable, as can be seen by not assigning a value:

 Module[{a},a]
 (*
 --> a$84
 *)

Finally, With:

With[{a=b}, Print[a]; a=3; f[x]+a]+foo[a,b]
(*
Prints: b
--> 3 + a + x + foo[a, 3]
*)

As you can see, the a=3 now globally assigns 3 to b! That's because With actually replaces a with the "assigned" value, i.e. b in the whole body. That is, whereever the body contains a it's as if there was written b instead. But again, the value of a in the called function f is not affected.

From this, one can get the following guidelines:

In the general case, you want Module because its effect is most localized. You want Block is you explicitly want to temporarily change a global value, e.g. Block[{$RecursionLimit=10000},RecursiveFunction[10000]]. And With should be reserved for cases where you actually want a literal replacement.

celtschk

Posted 2012-01-23T21:54:58.367

Reputation: 18 543

7

I think it is worth to point out another one peculiarity of With as compared to Module and Block which is little-known: With doesn't evaluate it's last argument at all, while both Module and Block evaluate their last arguments. In other words, the last argument of With will be evaluated only after leaving the With construct. This can be easily proven as follows:

With[{}, Stack[_]]
Module[{}, Stack[_]]
Block[{}, Stack[_]]
{}

Module[{}, Stack[_]]

Block[{}, Stack[_]]

One can see that in the case of With the stack is empty because evaluation of With is already finished when Stack[_] is being evaluated, while in the case of Module and Block the Stack[_] is evaluated inside of the scoping construct.


Another thing which is useful to know is that all these constructs support delayed assignments for local variables:

With[{a := Random[]}, {a, a, a}]
Module[{a := Random[]}, {a, a, a}]
Block[{a := Random[]}, {a, a, a}]
{0.637223, 0.284761, 0.180292}

{0.139856, 0.55708, 0.585556}

{0.888018, 0.961141, 0.451441}

Examples of use:

Alexey Popkov

Posted 2012-01-23T21:54:58.367

Reputation: 50 220

2That lack of evaluation allows With to support tail recursion (and as far as i am aware, that's exactly the reason for it). – Daniel Lichtblau – 2019-11-08T15:59:58.047

1@DanielLichtblau Just to be clear: by tail recursion you mean the sequental With (as With[{a = 0}, {a = a + 1}, {a = a + 1}, a]) or something else? – Alexey Popkov – 2019-11-08T16:44:10.147

I mean something else; check "tail recursion" on stack exchange to get the actual definition (a bit long for a comment). – Daniel Lichtblau – 2019-11-08T17:40:01.443

@DanielLichtblau Actually I already checked, but still do not understand how it is related to With. Can you provide an example?

– Alexey Popkov – 2019-11-08T17:49:02.140

@DanielLichtblau You've got me intrigued. Perhaps it is worth creating a separate question if the answer cannot fit in the comment? – Alexey Popkov – 2019-11-08T20:04:06.543

I will try to come up with an example if and when time permits. – Daniel Lichtblau – 2019-11-08T23:07:58.943