[racket] Again on bindings visibility in eval

From: Jos Koot (jos.koot at telefonica.net)
Date: Fri Jul 15 21:20:16 EDT 2011


-----Original Message-----
From: users-bounces at racket-lang.org [ <mailto:users-bounces at racket-lang.org>
mailto:users-bounces at racket-lang.org] On Behalf Of Mark Engelberg
Sent: viernes, 15 de julio de 2011 20:34
To: Sam Tobin-Hochstadt
Cc: users list; Matthias Felleisen
Subject: Re: [racket] Again on bindings visibility in eval

OK, so here are the main points I'm gathering from this discussion.

1.  Clojure's quasiquote system does some extra things behind the
scenes in terms of generating temporary variables and qualifying
variable names with their namespace in such a way that the macros you
write are reasonably hygienic.
2.  They are not perfectly hygienic because the gensym is simplistic
and there may be ways to defeat it if someone tried hard enough.
Also, rebinding the global things that the macro depends on may result
in unintended behavior.  (Then again, you could argue that if you
rebind the global "if", you really do want macros like "while" to
change.)

 
 



That certainly is not what I would want. In one of the first Lisp-like
languages I met (IBM) I redefined a macro such as to find out that many
other macros  where affected. Not my idea. We have to take into account taat
even a very experienced user  may not know which other forms are going to be
affected. SCOPE is important.
Jos






3.  Clojure does not have macros that are only valid within some local
context.  All macros are global, and this might result in a lack of
expressiveness versus Racket's system.
4.  Racket's macro system tracks things like source code location (and
possibly other things?) useful for debugging.

Point 3 is the main one I'm still getting my head around.  I had to do
a little research to understand what everyone was talking about here
with "local macros" and "scoped macros".  I see now that in Racket, if
you define a macro inside some sort of function body (or other lexical
scope), it is only valid within that scope.

Here are a couple of examples from Clojure to contrast that behavior with:
(def x 3)

(let [x 2]
  (defmacro apply-to-x [y]
    `(~y ~x)))

In this code snippet, x is a global, and apply-to-x is a global macro,
but the macro does look up x in its local context, i.e., (apply-to-x
identity) yields 2, not 3.

On the other hand removing the ~ from the x like this:
(let [x 2]
  (defmacro apply-to-x [y]
    `(~y x)))
causes the x in the macro to refer to the global x.  So, (apply-to-x
identity) yields 3.

So it is possible in Clojure to make the macro refer to its local
scope, but the macro itself is always global.

I recognize that this means there are things you can do in Racket with
macros that would be extremely difficult or impossible in Clojure, but
I don't have a good sense for how often this would occur in practice.
I gather it would be more of an issue for things on a large scale like
Racket's class system.
_________________________________________________
  For list-related administrative tasks:
   <http://lists.racket-lang.org/listinfo/users>
http://lists.racket-lang.org/listinfo/users 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20110716/58aa1259/attachment.html>

Posted on the users mailing list.