Skip to main content
added short advice on when to use which scoping construct
Source Link
celtschk
  • 19.3k
  • 1
  • 53
  • 107

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.

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.

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.

Source Link
celtschk
  • 19.3k
  • 1
  • 53
  • 107

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.