Loops and Scoping

For most simple tasks (i.e. most computations a chemist has to perform), making a notebook with a bunch of input and output cells is sufficient and possibly even best.

However, sometimes the task at hand is not so simple and so we'll need to progress to more complex structures.

Table and Do

Both Table and Do list over a range or a set of inputs and apply a function, example:

Table[i*i, {i, 10}]

(*Out:*)

{1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

Table[i*i, {i, {a, b, c, d, e} }]

(*Out:*)

{a^2, b^2, c^2, d^2, e^2}

The difference is that Table returns a List while Do returns either Null or anything returned from Return

Usually this means one wants to use Table , however this behavior gives Do two distinct advantages. The first is that Table must return something at every step, while Do used in conjunction with Reap and Sow need not. For example let's get the prime numbers between 1 and 1000:

Reap[
  Do[If[PrimeQ[i], Sow[i]], {i, 1000}]
  ][[2, 1]]

(*Out:*)

{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643,
647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
941, 947, 953, 967, 971, 977, 983, 991, 997}

Table would return Null every time there wasn’t a prime meaning we’d have vastly too many outputs.

Secondly and most critically, Do can go over an infinite range, when used with Break or Return which acts like a While[True, body] loop, but cleaner. In general, Do can be used in this way whenever While would have been used. For example:

Do[If[RandomReal[] < .00001, Return[i]], {i, ∞}]

(*Out:*)

210319

This simulates the following loop:

i = 1;
While[RandomReal[] > .00001,
  i += 1
  ];
i

(*Out:*)

184158

But Do is a cleaner construct, owing to its automatic scoping of the i and implicit incrementor

Module, With, and Block

Module , With , and Block are called scoping constructs. That is, they let you use a variable or multiple variables without having to change or set them globally, or. This is easiest to show in an example:

Consider the following chunk of code:

a = 2;
squareA[] := (a = a*a);
{squareA[], squareA[], squareA[]}

(*Out:*)

{4, 16, 256}

Then check the current value of a

a

(*Out:*)

256

Now try checking a in a Module where the variable a has been scoped

Module[{a},
 a
 ]

(*Out:*)

a$736

Notice that the value of a is not its global value. This is because Module creates its own scope to execute the code in.

This is the basic use of a scoping construct, protecting code from being influenced by the global state.

Each construct has its own peculiarities, but these will be discussed more later. For now, we’ll only discuss Module as its usage is the clearest.

Module

Module has the following form:

Module[{var1, var2, ..., varn},
 codeBlock
 ]

where var1, var2, ..., varn are either simple variable names or variable names with initial values.

Past that, one can write code with Module just as one would normally.

Consider the following:

Module[{v1, v2 = 10, v3 = 50, v4},
 v3 = 10;
 v4 = v3*v2;
 {v1, v2, v3, v4}
 ]

(*Out:*)

{v1$739, 10, 10, 100}

The code executes just as one would expect, the only difference being that v1 has been renamed. If one runs the following it becomes clear how Module works:

Module[
  {v1, v2 = 10, v3 = 50, v4},
  v3 = 10;
  Clear@v4;
  {v1, v2, v3, v4}
  ]

(*Out:*)

{v1$740, 10, 10, v4$740}

All module does is replace each variable in the first argument with the variable name followed by $i where i is an integer (given by the value of the global variable $ModuleNumber when the Module is executed).

results matching ""

    No results matching ""