Reflection in Scheme

I’ve been mulling over this idea for a while.

Now that I’ve been programming (exclusively) in Scheme for the past two years, I realized that I have slowly — but surely — learned to accept and embrace one of the most controversial surface syntax in a programming language: the S-Expression.

The criticism to sexpr syntax are numerous, and most of them can be seen as silly once you have gotten used to it, however here lies the problem: most people never get past their initial reaction to sexpr. They see the parenthesis and just freeze up.

Lispers and Schemers are the first to point out the advantages to having such a syntax: it’s simple, easy to understand and parse, and concise. In the end, however, it actually all boils down to just one single thing: We know how to write awesome macro systems with a sexpr surface syntax.

And this is all well and good.

However, now that we have decided to stick with this syntax, and we have used it to our advantages to write many wonder macro systems, what else can we do with this decision?

In Scheme, when you write down a list of four elements, beginning with the word list like this:

(list 'apple 'banana 'cactus) => '(apple banana cactus)

You get a list with three elements. You can query it in the following ways:

(list?  '(apple banana cactus)) => #t
(length '(apple banana cactus) => 3
(first  '(apple banana cactus))   => apple
(last   '(apple banana cactus))   => cactus

So you are able to find out that it is a list, and from that, its length and its first and last element.

This is elementary stuff, and anyone learning Scheme would know this by the end of their first week in class. However, what about this?

(define hello (lambda () (display "Hello")))

This is again a list, of three elements. The first element is define, then hello and last is another list (which begins with the word lambda).

In R5RS Scheme, there’s virtually nothing you can do to query this structure. The most that you can do, as far as I know, is with MIT Scheme’s procedure? and procedure-arity procedures, which corresponds to list? and length for lists.

Wouldn’t it be cool if one could manipulate Scheme code (procedures) as easily as one could manipulate Scheme data (lists, vectors)? I don’t mean that there should be a procedure-car and procedure-cdr, but something more specific, like procedure-name and procedure-body. This can be extended to other constructs as well. Given:

(if (list? l) (length l) 0)

We could have

(expression-type? ##) => <if-expression>
(if-test          ##) => (list? l)
(if-then-clause   ##) => (length l)
(if-else-clause   ##) => 0

Why hasn’t this been done before? I did some literature research, and am surprised to see so little on this topic.

Recently, I came across Charlotte Herzeel’s talk at the S3 workshop, but I think she’s going about it in the wrong way because she’s only thinking about the manipulation of code as lists, using variations of car and cdr instead of something with more specific semantics attached to it. Perhaps her background in Common Lisp (instead of Scheme) maybe have something to do with that.

3 Comments

  1. Eric Hanchrow:

    I was under the impression that McCarthy’s original Lisp did just what you want: represented procedures as plain old lists whose first element was the symbol “lambda”. Something tells me this turned out to be a bad idea, which is why it’s no longer done. I will bet you that Eli Barzilay will be able to tell you the pros and cons.

  2. Raoul Duke:

    i wonder about reflection in lisps/schemes, too.

    i also wish we could figure out how to have nice macros in non s-expr languages somehow.

  3. Raoul Duke:

    p.s. for macros, i started learning Nemerle a while ago but didn’t get into the macro part, but i wonder if they have a good enough approach for non s-expr syntax: http://nemerle.org/Macros

Leave a comment