Stephen Compall <stephen.comp...@gmail.com> writes:

> On Tue, 2011-12-06 at 16:09 +0100, Tassilo Horn wrote:
>> Wikipedia lists syntax-case as hygienic macro system, which would
>> make it less powerful than CL macros, because if that was true, you
>> could not write anaphoric macros with it.
>
> You can write anaphora with syntax-case.  In fact, defmacro itself can
> be defined as a simple syntax-case macro.

Ok, I see.  I'm still keen to see a simple syntax-case example
demonstrating what you simply cannot do with defmacro.

In the mean-time, I've found some post about Racket's macro
implementation:

  http://blog.racket-lang.org/2011/04/writing-syntax-case-macros.html

That says the fundamental difference between defmacro and syntax-case
macros is that the latter

  "instead of dealing with plain symbols, you're dealing with these
  syntax values (called “identifiers” in this case) that are essentially
  a symbol and some opaque information that represents the lexical scope
  for its source."

Do I see it correctly that the following Common Lisp defmacro is broken
because of that missing lexical scope?

--8<---------------cut here---------------start------------->8---
* (defun my-plus (&rest xs)
    (apply #'+ xs))
MY-PLUS
* (defmacro foo (&rest xs)
    `(my-plus ,@xs))
FOO
* (foo 1 2)
3
* (labels ((my-plus (&rest xs)
             (apply #'- xs)))
    (foo 1 2))
-1  ;; Ouch! my-plus should not shadow macro expansion internals!
--8<---------------cut here---------------end--------------->8---

Here, the local function `my-place' captures the global definition of
`my-plus'.  First, I've thought I could easily get rid of that issue by
using my-plus's package qualified name, but I was wrong:

--8<---------------cut here---------------start------------->8---
* (defmacro foo (&rest xs)
    `(common-lisp-user::my-plus ,@xs))
FOO
* (labels ((my-plus (&rest xs)
             (apply #'- xs)))
    (foo 1 2))
-1
--8<---------------cut here---------------end--------------->8---

Am I doing something wrong, or is there no way to avoid that capture in
CL?  (Possibly, CL explicitly forbids rebinding standard CL function
names for exactly that reason.)

That said, in Clojure the example works fine, because everything inside
the macro expansion is qualified.

--8<---------------cut here---------------start------------->8---
user> (defmacro foo [& exps]
        `(+ ~@exps))
#'user/foo
user> (foo 1 2)
3
user> (let [+ #(apply - %&)] (foo 1 2))
3
user> (macroexpand '(foo 1 2))
(clojure.core/+ 1 2)
--8<---------------cut here---------------end--------------->8---

And the other way round, passing functions into macros, works also fine.
For example, here the rebound + shadows clojure.core/+, which is clearly
intended.  (Of course, this works fine in CL, too).

--8<---------------cut here---------------start------------->8---
user> (defmacro bar [x & args] `(~x ~@args))
#'user/bar
user> (let [+ #(apply - %&)] (bar + 1 2))
-1
--8<---------------cut here---------------end--------------->8---

Does that mean that Clojure's defmacro is aware of the lexical scope as
well and is therefore equally powerful as Scheme's syntax-case?

Bye,
Tassilo

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to