Dynamically Scoped Variables

Just as Peter continues to be amazed by Wikipedia, so do I. Today I noticed that David Jenkins, who I used to work with, wrote an article about a programming
language called Magik that forms the basis of Smallworld GIS.

Magik was revolutionary for its time – a dynamic/strongly typed object-oriented language used to build large mission critical applications. It shares many similarities with Smalltalk and Ruby, including mixins, closures, procs, etc.

And one thing it has that Ruby doesn’t is dynamic variables. Dynamic variables
have been around a long time, LISP has them as does PERL. But if you’ve never
worked with dynamic variables they are a bit weird. At least I thought so.

The basic idea is that when you set the value of a variable it will override any previous values for the remainder of that scope but then return back to its original value at the end of the scope. Thus a dynamic variable acts just like a stack.

Let’s take a look at an example from Wikipedia:

int x = 0;
int f () { return x; }
int g () { int x = 1; return f(); }				

If you call g() what’s the result? Well, most people would say 0 which is true for lexically scoped variables. But for dynamically scoped variables it is 1. See why? In g we override the value of x and make it 1. That value remains the current value as g calls f and accesses x. Once we return out of g, x reverts back to its original value of 0.

Reading Paul Graham’s On Lisp, it turns out that LISP started with dynamically
scoped variables. However, it turns out that lexically scoped variable are generally more useful because they are easier to understand and enable the use of closures. If you think about it for a second, you’ll see that dynamic scoping doesn’t work well with closures since the whole point of a closure is to capture the current value of a variable.

So, why would you use dynamic variables? For the longest time I didn’t see much use for them. But in turns out they are quite useful in multi-threaded applications. Imagine you’ve written a gis server (ala ArcIMS, MapServer or Smallworld
IAS
) and each client can request a map in a different projection. That means that your map rendering code has to have access to the current projection. One simple way to do this is via dynamic variables. Set the dynamic variable at the start of the request and have the map rendering code access its value. Something like this (in pseudo Magik no less!):

# Create a global variable
_global current_projection = 'epsg4326'

_method process_request
  # Override the default value as a dynamic variable
  _dynamic current_projection = 'epsg9822'
  
	 # Do some stuff
  ...

	 # Render map
  self.render_map()
_endmethod

_method render_map
  # Access dynamic variable
  _if current_projection == 'epsg4326'
  _endif
_endmethod   
      

Although it looks like the render_map code is accessing a global variable, it in fact is accessing a dynamically set variable. Thus this code is fully thread safe.

For the case above you can fake dynamic variables by using thread-local storage. In fact, Christian Neukirchen has used this technique to implement dynamic
variables in Ruby.

Now, let’s get back to my post yesterday about Rails and HTML/XHTML generation. If you write an application server, you’ll found out sooner or later that just about every piece of code needs access to the request and response objects. I suppose this might seem obvious, but it took me 2 years and 3 release of SIAS to finally see the light. My resistance was from fear of creating too tight a coupling between different parts of the system.

Rails of course has the same issue. The general solution, and the one Rails takes, is to pass around a reference to an object that holds the information you need. For rails, that is the controller object which in turn has references to the request and response objects. However, it doesn’t work quite as well as you would like, as I explained yesterday. And woe to you if you want to change it – then you really are touching every part of the system.

In contrast, dynamic variables provide a cleaner solution. All parts of the code have access to the necessary information, and you don’t have to pass object references as method parameters all over the place. Thus you end up with less code, and in fact, less inter-module dependencies.

So although a seemingly obscure programming language construct, dynamically scoped variables can come in handy in the right situations.

  1. Jason Watkins
    April 13, 2006

    I’m not so optimistic about dynamic variables. I believe it’s fairly clear the LISP community learned they weren’t worth it.

    If your issue is distributed/mutli-threaded codeing, there’s a plethora of other options. One that’s particularly closure compatable is distributed lexical scope (look up the language Obliq by cardelli).

    In the example above, I don’t understand what the objection is to passing in current_projection as a parameter (or for a more OO approach, accessing it through self).

    Likewise, in your original motivation I’d just look for a way to make accessing the response type consistent.

    Reply
  2. Charlie Savage –
    April 13, 2006

    Hi Jason – thanks for the comments and the reference to Obliq, it looks quite interesting.

    I agree there are lots of ways to solve this issue. The main advantage I see for using dynamics is that it provides a non-intrusive way of passing information between two pieces of disconnected code. That can be handy when working on an existing code base where you can’t add in additional method parameters because it would break too much other code.

    Using the rails example, I end up with ugly code in the tag method because its mixed into various objects. Thus I have to use instance_of to figure out what object the tag has been mixed into, and take the appropriate action. This can be alleviated to a large degree by adding a controller method to each object, thus providing at least a consistent API and getting rid of the ugly runtime check.

    Other than this case, I haven’t found much use for dynamics. It would be intresting to hear comments from other people about when and why they use dynamics variables.

    Reply
  3. August 5, 2008

    I’ve used dynamic variables to make code DRY in cases where you couldn’t make code DRY before. I am sure there are other ways to do the things I was doing.

    The way PHP does it is super accessible: http://us3.php.net/variables.variable.

    I wish I could find a way to do it in Ruby

    Reply

Leave a Reply

Your email address will not be published.

Top