| With the new fexpr-based interpreter for wart[1] I've been trying to reduce the set of names in the core language and bootstrap complex features by progressive enhancement. For example, I'd like to build arc's if out of a simple two-branch if as follows: let oldif if
mac if args
oldif (no (cdr args))
(car args)
`(,oldif ,(car args)
,(cadr args)
(if ,@(cddr args)))
But macros must evaluate in the caller's lexical scope. mac foo(x)
`(+ ,x 1)
let y 3
(foo y) ; must macex to (+ y 1) in foo's scope, then evaluate to 4 in caller scope
The solution I'm trying out to get both these macro examples to work is a sort of gracefully degrading lexical scope. At every call, instead of swapping in the callee's environment, I push it above the caller's environment. This is like lexical scope in how bindings override each other: (let x 3
def foo()
(let x 4
(bar))
def bar()
x)
(foo) ; returns 3 from the outer lexical scope
But it also makes the caller's lexical scope available if necessary: def bar()
x
let x 3
(bar) ; returns 3 like a dynamic scope
I haven't seen this idea before, and I'm inclined in this case to think it's probably a bad idea. Can anyone think of use cases where having the extra power bites us? Feel free to play with wart: $ git clone
$ git checkout 4863b4318f
$ wart
One drawback I found was that macros must now almost always use implicit gensyms[1] to avoid overriding bindings in their callers. The correct definition for if in this scheme is: let $if if
mac if $args
$if (no (cdr $args))
(car $args)
`(,$if ,(car $args)
,(cadr $args)
(if ,@(cddr $args)))
If this macro's parameter was just args it wouldn't have access to any other bindings at macro call-sites using the variable args. It must be a gensym. if args
prn "hi" ; requires gensyms in 'if' macro
I'm still playing with this to see how onerous it is to have all these $vars in macros. If it's not too onerous, and if we don't discover any other issues, it would mean that I can build macros out of just eval and implicit gensyms and lexical scopes.[1] http://arclanguage.org/item?id=14881, http://github.com/akkartik/wart/tree/unstable [2] http://arclanguage.org/item?id=13342 |