fun.py |
|
---|---|
|
|
Functions |
|
As you might have imagined, McCarthy's Lisp derives much of its power from the function. The |
|
Evaluation just delegates out to the builtin. |
|
λ λ λ |
|
The real power of McCarthy's Lisp srpings from Alonzo Chruch's λ-calculus. |
|
The names that occur in the arg list of the lambda are bound (or dummy) variables |
|
Unlike the builtin functions, lambdas have arbitrary bodies |
|
Every invocation of a lambda causes its bound variables to be pushed onto the
dynamic bindings stack. McCarthy only touches briefly on the idea that combining functions
built from lambda is problemmatic. In almost a throw-away sentence he states, "different bound
variables may be represented by the same symbol. This is called collision of bound variables." If you
take the time to explore core.lisp then you will see what this means in practice. |
|
The bindings are set one by one corresponding to the input values. |
|
The evaluation of a lambda is not much more complicated than a builtin function, except that it will establish bindings in the root context. Additionally, the root context will hold all bindings, so free variables will also be in play. |
|
Dynamic scope requires that names be bound on the global environment stack ... |
|
... so I do just that. |
|
Now each form in the body is evaluated one by one, and the last determines the return value |
|
Finally, the bindings established by the lambda are popped off of the dynamic stack |
|
Closures |
|
McCarthy's Lisp does not define closures and in fact the precense of closures in the context of a pervasive dynamic scope is problemmatic. However, this fact was academic to me and didn't really map conceptually to anything that I had experienced in the normal course of my programming life. Therefore, I added closures to see what would happen. It turns out that if you thought that bound variables caused issues then your head will explode to find out what closures do. Buyer beware. However, closures are disabled by default. |
|
It's hard to imagine that this is the only difference between dynamic and lexical scope. That is, whereas the latter established bindings in the root context, the former does so only at the most immediate. Of course, there is no way to know this, so I had to make sure that the right context was passed within lithp.py. |
|