[racket] Again on bindings visibility in eval

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Jul 15 03:11:40 EDT 2011

Three hours ago, Mark Engelberg wrote:
> On Thu, Jul 14, 2011 at 4:35 AM, Thomas Chust <chust at web.de> wrote:
> > While Clojure *mitigates* the problems of non-hygienic macros
> > using namespaces and a shorthand syntax for freshly generated
> > identifiers, it doesn't *solve* the problems. Racket's macro
> > system, on the other hand, does solve the problems and since that
> > involves some heavy lifting, it may seem more complicated at first
> > glance.
> I would like to better understand how Clojure's mitigation strategy
> is insufficient.  Since Eli's document is all about the while macro,
> let's look at Clojure's while macro.

I know very little about clojure, so I don't have a clue how this code
works.  But one thing that seems fishy: I used your code as is, but
before entering it, I entered

  (defmacro when [test & body]
    `(if ~test ((fn [] (println "in my when") ~@body))))

and it got into an infinite loop (and printed "in my when").
(I couldn't figure out clojure's `begin' equivalent, so I did it the
stupid way).  I tried to read around and figure out why that happens,
but I still don't see the problem.

In any case, it looks like clojure macros are closer to racket than
they are to CL -- with ` being roughly similar to #` (it's even called
"syntax-quote").  So I also don't know whether there's something that
is misbehaved there.  On thing that I did try is:

  (defmacro myif [x y z] `(if ~x ~y ~z))
  (defmacro myor [x y] `(let [t# ~x] (myif t# t# ~y)))
  (let [myif ...] (myor ...))

and that doesn't break too -- it *looks* like `myif' is a plain symbol
when expanding the last expression, which somehow gets qualified by a
namespace later.  Based on this, I tried to dig more with local
macros, and I found out that clojure doesn't have them.  Whatever
clojure does, I think that prohibiting local macros is important.  (I
see that there's some library with it, but that goes well beyond my
interest/tiredness threshold.)  Either that, or there's some way to
have "uninterned namespaces".

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

Posted on the users mailing list.