In Defense Of Dynamic Variables

Published on Thursday, June 29th, 2017


Dynamic variables are neat. I know that they've got somewhat of a
bad rep as being error prone and anachronistic, but I think they
have a well-deserved place in the everyday hacker's toolbox.

But first -- a small recap: dynamic (or special in lisp parlance)
variables are variables whose locations are determined during run-
time. The locations of static (or lexical) variables are -- you
guessed it -- detemined before the code is being run.

The advantage of static variables is that you can easily reason
about them as they typically flow along lexical structures in the
code, such as blocks and function-definitions. The problem with
them is that they can be a bit stiff-necked when you want to
temporarily alter the behavior of a piece of code.
Consider this: if you want to change `*stdout*` to a custom stream
in a language that only allow lexical variables, you either need to
pass an extra parameter to every function that make use of `*stdout*`
or you need to have a global variable that will alter the behavior
for the entire program. (And you still need to point the functions
that use `*stdout*` to use the global variable instead.)

Dynamic variables allow you to reference to values that potentially
may not exist. This is of course a great source of potential errors,
but when used carefully, they will help in making code more
composable and elegant than what a strictly static language will
allow.

I like to think that formal, lexical parameters of a function form
a horizontal axis and informal, dynamic variables form a vertical
one, and that they together span a two-dimensional space of the
possible inputs of a function. (The challenge is to make the
informal dimension as apparent as the formal parameters. I'll have
to come back on that. :>)

Elsa supports both lexical and dynamic variables, but with a slight
twist. They are not separated in different environments as they are
in Common Lisp. As a result, dynamic variables are resolved along
the call-stack. At the call-site, it will unwind the lexical
blocks until it finds the matching name. This means that you can
effectively peek back on the caller's environment in order to
determine how the callee should run.

Time will tell if it's a good move to do it like this, but I'm sure
you'll find that dynamic variables are a pretty nice addition to
your arsenal.

<3 jzp