archives

Lisps, First-Class Special Forms, Fexprs, The Kernel Programming Language

I've been thinking about macros vs. fexprs on and off for about a year. The following bit of Scheme code exposes, what seems to me, a troublesome difference between function application and special forms.


(define (a) 1)
(define (alpha) (a))
(alpha)             ;  1
(define (a) -1)
(alpha)             ; -1

(define-syntax b (syntax-rules () ((_) 2)))
(define (beta) (b))
(beta)              ;  2
(define-syntax b (syntax-rules () ((_) -2)))
(beta)              ;  2 still!

The function being applied, a, in the first half of the code above, is dynamically determined when the application occurs. A redefinition of a means that calling alpha will reflect that change. Dynamic languages. Late binding. Yay!

In the second half of the code above, the special form, b, is determined and expanded when beta is first defined and redefining b has no affect on later calls to beta.

I know this is an old issue but looking at John Shutt's reasonably recent The Kernel Programming Language (and on wikipedia and here) he seems to have "solved" the problem by inventing $vau expressions which fall roughly into the fexprs category.

It seems a long time ago that Kent Pitman argued influentially against fexprs because they did not play well with the Lisps of 1980 with their dynamically scoped variables. The Kernel Programming Language has lexically scoped variables and the $vau form is not one considered by Pitman.

I've can only find mention of John Shutt's language once on Lambda the Ultimate and am surprised the $vau expression idea has not received more attention. It seems like a great idea enabling a more dynamic and consistently defined language.

In-Progress MSc on DSL Program Maintenance

I'm a grad student at the University of Toronto. My thesis is a case study of DSL maintenance. If you use DSLs in your work, and you can spare half an hour for a non-personal non-confidential interview, please get in touch! ad@cs.toronto.edu.