Throwing off our scope chains

1,706 reads

Eve gets away with just one global scope and one local scope

Welcome to Part III of my VI-part series about Eve, an exciting and fascinating new programming language.

Lexical scoping has been a fixture of mainstream programming for decades. But while it enables some elegant patterns, it also adds incidental complexity by making it hard to reason about the state of your program.

If we pause a typical program in the debugger, it’s pretty overwhelming to see all the obscure little pools of state being kept around in memory:

Scope that’s local to the current function or block A chain of closures storing local variables for all blocks of code which the current block is nested in Additional chains of closures, one for each function that we can access from our current scope

Here’s a simple example:

Look at all the little pools of state that exist when we get to line 14:

bWithScopeChain and value are local to g fVar is one level up the scope chain, part of Closure (f) aVar isn’t anywhere in g ’s scope chain, but its value of 1 is still alive and well in memory because it’s currently in the scope chain of bWithScopeChain

Lexical scoping feels like a nice way of doing things when you’re coding up f . But when you’ve run f() and now something isn’t working perfectly, lexical scoping is suddenly a nightmare, because there’s no way to tap into any of f ’s state from the command line. What can you do?

We both know you’ll probably get jiggy with some console.log action. Unless you prefer to use the debugger to step through your program, which is every bit as convenient as using Google Earth to visualize the Mississippi river… while stuck at maximum zoom.

There’s a way out of this mess. With Eve, we only have to deal with two scopes:

Local scope

Each block of Eve code can have its own local variables

Each block of Eve code can have its own local variables Global scope

Any state that persists from one timestep to the next must live in some database, and any part of the program may query any database

Eve doesn’t have scope chains because you can’t nest code blocks into other code blocks. It’s all very flat; there’s nowhere for obscure little pools of state to hide. Which also means Eve can’t have closures, because closures are by definition a mechanism for creating obscure little pools of persistent local state.

It’s still early to know how feasible it is to program without scope chains. We don’t yet know how well we can live without lexical scope, because language support for writing functions in Eve 0.2 isn’t fully baked. It’s possible that lexical scoping is a major help to writing a certain type of program, perhaps an algorithm-heavy one like a chess AI.

Still, for many of us programmers, “shunting data around”, a.k.a. writing “glue code”, is where we spend much of our time. That part of the job is also where it’s easiest to imagine living without lexical scope. So we can look forward to throwing off our scope chains because even if we don’t end up using Eve everywhere in our codebase, we’ll get a lot of value from using it in some parts.

Next post:

IV. Smalltalk and protein programming

Tags