## mht.wtf

A blog about computer science, programming, and whatnot.

# Mathematica's Scoping is Weird

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;
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;
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?