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.
- I. How Eve unifies your entire programming stack
- II. When logic programming meets CQRS
- III. Throwing off our scope chains
- IV. Smalltalk and protein programming
- V. The rock-solid foundation for Eve’s big vision
- VI. Why Eve will be perfect for realtime apps
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:
valueare local to
fVaris one level up the scope chain, part of
aVarisn’t anywhere in
g’s scope chain, but its value of
1is still alive and well in memory because it’s currently in the scope chain of
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
- 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.
IV. Smalltalk and protein programming