Tuesday, June 9, 2015

Use Block to Temporarily Block Global Variables

The main Mathematica scoping function to learn is Module. For occasional special purposes, use Block to temporarily store and then restore Global variables, and use With to fix local variables so they can't be accidentally changed inside of With.

Use any Doc Center page for a scratchpad (not Block), since all variable names and values are localized to that page and are automatically cleaned up when you leave the page.

Block does two things:
  1. Temporarily stores a Global variable value and then restore it
  2. Uses a local value for the variable in the Block if you give it one
Here is a step-by-step example of how Block works.

x=17;
Block[{x=4},x^2]
16

x
17

Step
Effect
x = 17;
Variable x is Set to 17 in the Global` Context
Block[{x=4},x^2]
A Block is entered using specifying a local variable with the same name as the Global one (x = 4)
Within Block: x$23 = x
Local, temporary variable x$23 is Set to x’s global value of 17
Within Block: x = 4
Local, temporary variable x is Set to 4
Within Block: x^2
In Power[x, 2] x replaced by 4: Power[x, 2] /. x -> 4
Block returns 4^2 = 16
Locally with Block Power[x, 2] evaluates to 16, which is returned
Block Sets x = x$23 and exits
The Global value of x is restored
x
The Global values of x is called
17
The Global value of x is returned

Typical Uses of Block

Block is used to scope and protect the iterators in Table, Do, Sum, etc. If you write a function with an iterator you can use Block.

More typical uses of Block are to change the value of system environment variables such as decreasing $RecursionLimit or $IterationLimit to prevent infinite looping while you're debugging a function, or increasing them to solve a deeply nested or iterated calculation.

An interesting combinatorial series arises from the number of partitions of integer sets, the Bell number. Pemmaraju and Skiena compute it recursively. To let the function solve for indefinitely large sets, $RecursionLimit is temporarily set to Infinity within the Block and automatically restored to its default value after execution.

Clear[bellB,bellB1];

bellB@n_Integer:=bellB1@n;
bellB1@0=1;(*base case*)

bellB1@n_:=Block[
{$RecursionLimit=Infinity},
bellB1@n=Sum[Binomial[n-1,k]*bellB1@k,{k,0,n-1}] (*memo function*)
]

bellB/@Range@10
{1,2,5,15,52,203,877,4140,21147,115975}

$RecursionLimit

1024

Why Block Might Not Seem to Work

Again, if you understand that Block will 1) temporarily store a Global variable value and then restore it, and 2) use a local value for the variable in the Block only if you give it one, you will understand the following examples. First, we Set x equal to 25 in Global`.

x=25;

Here x isn't scoped and so isn't Blocked; Mathematica can't just assume you wanted it localized.

Block[{},x]
25

Here x is scoped but we didn't assign it a new value. So while its global value of 25 was stored in a temporary variable it was also used in Block.

Block[{x},x]
25

Now we assign a value to x in Block's scope, or in its body. Block works as intended.

Block[{x=5},x]
5

Block[{x},x=5]
5

And x's Global value was restored as Block closed itself out. All is good in the universe :-)

x
25


Block Compared with Module and With

Block and Module let us change scoped variable values in the body of their code.

Block[{x=5},Print@x;x=50;x]
5
50

Module[{x=15},Print@x;x=100;x]
15
100

But With does not; we get an error message. When we try to Set x to 8, Mathematica sees "2 = 8":

With[{x=2},Print@x;x=8;x^2]
2
Set::setraw: Cannot assign to raw object 2. >>
Out[292]= 4

Block and Module immediately use scoped variable values, so here Mathematica sees "5^2 /. 5 -> 6", evaluates 5^2 as 25 and thus sees "25 /. 5 ->6"; there's no x to replace.

Block[{x=5},x^2/.x->6]
25

Module works by creating a special local variable name for each scoped variable. Here, within the Module, x lives on under the new name "x$485":

Module[{x},Print@x]
x$485

No comments:

Post a Comment