December 30, 2021

I’ve been using Mathematica a little bit in the past few weeks to do some simple plotting and symbolic manipulation of equations.
It’s *okay*; I keep running into weird behavior and getting funny errors that I assume
more seasoned Mathematica users would not get. Here’s one of them.

`With`

Mathematica has weird scoping rules. For instance, there’s a thing called `With`

that let’s you assign values to
variables in some expression and then have these values be replaced in that expression.
It feels similar to a regular block in C-like languages.
It looks like this:

```
In[1]:= With[{x=1}, x+1]
Out[1]= 2
```

No surprise so far, since `1 + 1 == 2`

. However, what happens if you make a new variable in the expression in a `With`

?

```
In[2]:= With[{}, inner=1]
Out[2]= 1
In[3]:= inner
Out[3]= 1
```

Okay, so `inner`

has now leaked out to the global scope. Annoying, since it might be difficult to avoid
having symbols leak out of your scope, but maybe it’s not so bad.

`Block`

Another similar form to `With`

is `Block`

, which is used for dynamic scoped variables.
Assume we have a bunch of values that we don’t want to keep passing around all functions that we use.
For instance we can have a function that just adds its argument to some “global” symbol:

```
In[1]:= addX[a_]:=a + x
```

Here `x`

is a free variable in the function `addX`

. We can evaluate the function and assign a value to `a`

:

```
In[2]:= addX[12]
Out[2]= 12+x
```

We can also define `x`

to be some value.

```
In[3]:= x=3;
addX[12]
Out[4]= 15
```

Maybe we would like to evaluate `addX`

but use a different temporary value for `x`

. We can use `Block`

for this:

```
In[5]:= Block[{x=10}, addX[10]]
Out[5]= 20
```

This does not change the value of `x`

```
In[6]:= x
Out[6]= 3
```

Using the other construct from the beginning, `With`

, does not work the same way,
since the `addX`

function will already look up the global value of `x`

when it is evaluated.
In a sense, `Block`

makes references to `x`

give higher precedence to the `Block`

value instead of the global value.

```
In[7]:= With[{x=10}, addX[10]]
Out[7]= 13
```

This might be surprising, but hey, different constructs for different semantics;
presumably there are times when you’d want `With`

semantics and other times when you want `Block`

semantics.

Another problem arise when we have an old variable still in the notebook, maybe introduced from a scope you thought was local. Consider the following

```
In[8]:= Block[{y=10, x=y+10}, addX[10]]
Out[8]= 30
```

So far all is well; `y`

is 10, `x`

is 20, and we add 10 to `x`

which gives us 30.
What happens now if we add a global variable named `y`

?

```
In[9]:= y=0;
Block[{y=10, x=y+10}, addX[10]]
Out[10]= 20
```

We get a different answer!
It turns out that when `Block`

evaluates its arguments, it does so without binding the values it creates as dynamic,
so the evaluation of `x=y+10`

does not use the newly made variable `y`

but rather the global value `0`

.
Unless, of course, `y`

has no value yet, in which, I guess at a later stage, it is bound to the value introduced by `Block`

.
Makes sense? No?

Presumably this is documented somewhere in the language specification, if you just know where to look and exactly how the language works. But man, this is not intuitive.

Pointers, complaints, suggestions, and your bitcoin wallet, can be sent to my public inbox (plain text emails only).

Thanks for reading.

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License