[racket] redefining #%top (and #%app) with conditions

From: Matthew Butterick (mb at mbtype.com)
Date: Thu Feb 6 23:38:52 EST 2014

I'm trying to figure out how to make #%top change behavior based on different kinds of function names, though my experiments keep leading to infinite loops that blow up DrRacket. Oops.

In my #lang project based on Scribble, I've been using this simple redefinition of #%top for convenience:

(define-syntax-rule (#%top . id)
    (λ x `(id , at x)))

IOW, if the thing in the function position is undefined, it's treated as the opening tag of an x-expression. This makes it easy to mix undefined and defined names.

But it can make debugging difficult. Because if you expect a name to be defined as a function and it isn't, then you don't get the syntax error you ordinarily would. The function call silently gets converted an x-expression. Spooky side effects follow.

I'd like to improve this by making a syntactic prefix that suppresses this behavior and that can be attached to any function name. For instance, def-*. So if I write (def-foobar ..) in the code, this will mean:
1) try to invoke a function called (foobar ...); 
2) if the function (foobar ...) isn't defined, raise the usual exception + syntax error.
In other words, the standard #%top behavior.

Whereas if I just write (foobar ...) without the def-* prefix, this will mean:
1) try to invoke the function (foobar ...); 
2) if the function (foobar ...) isn't defined, turn it into the x-expression `(foobar ,@ ...). 
In other words, my special #%top behavior shown above.

Having explained the logic, I think the flaw in my experiments so far is that this actually requires manipulation of #%app too, because once you hit #%top, you've missed your chance to apply functions. (Right?) But even supposing one creates two evaluation paths under #%app, it's not clear to me how to preserve those paths on the way up to #%top.




Posted on the users mailing list.