You are right, Ken. I was a little bit sloppy regarding macro
expansion. The macroexpand1 method (line 5275) called by analyzeSeq
quits immediately, if the operator is a special symbol. Thus, 'if'
cannot be overwritten by a macro as you demonstrated with your if-
defmacro example, only the use of a qualified name can.

Regarding your qqq-defmacro example, you seem to be onto something.
>From reading the code in Compiler.java, I don't get (yet), why this
does not work as expected, but there is a comment left in method
analyze saying in line 5155:

    // todo symbol macro expansion?

Maybe that's the issue here. Possibly, some code is missing covering
your case.

Interestingly, macroexpand does not work on your qqq-macro either:

user=> (macroexpand '((qqq) (even? 42) "boo!"))
((qqq) (even? 42) "boo!")

That's weird.

Dominikus

On 15 Mrz., 01:24, Ken Wesson <kwess...@gmail.com> wrote:
> On Mon, Mar 14, 2011 at 6:32 PM, Dominikus <dominikus.herzb...@gmail.com> 
> wrote:
> > I did some investigations on the code in Compiler.java. There is an
> > IPersistentMap called 'specials' (line 95, Clojure 1.2) that maps
> > symbols like 'if' to parsers like IfExpr.Parser(); obviously, these
> > are the parsers recognizing special forms.
>
> > Method analyzeSeq (line 5347) tries macro expansion first and gets the
> > operator of a sequence form next. There is some special behavior if
> > the operator is FN (namely 'fn*' for which no parser is associated in
> > 'specials'; I don't know why 'fn*' gets special treatment here), then
> > special parsers are activated if the operator is a special symbol,
> > otherwise InvokeExpr.parse() is run.
>
> That doesn't quite seem right:
>
> user=> (defmacro if [x y] `(println ~x ~y))
> #'user/if
> user=> (if (even? 42) "boo!")
> "boo!"
> user=> (user/if (even? 42) "boo!")
> true boo!
> nil
> user=>
>
> Clearly, the if special symbol, when in operator position, shadows
> even macros, forcing the use of a fully-qualified name to employ a
> macro named "if".
>
> Perhaps you meant it does macroexpansion of the subforms first, but
> not (yet) of the whole form? Then it checks for the whole form to be a
> special form; then for the whole form to be a macro in need of
> expansion; and then treats it as a function call.
>
> If so, it's only the subforms not in operator position that get
> macroexpanded first. Otherwise
>
> user=> (defmacro qqq [] 'if)
> #'user/qqq
> user=> ((qqq) (even? 42) "boo!")
> #<CompilerException java.lang.Exception: Unable to resolve symbol: if
> in this context (NO_SOURCE_FILE:607)>
>
> would instead produce "boo!", as (qqq) would be expanded to if and
> then (if (even? 42) "boo!") would be parsed and discovered to be an if
> special form.
>
> On the other hand,
>
> user=> (quote (qqq))
> (qqq)
>
> seems to indicate that nothing is macroexpanded before special form
> parsing occurs, or it would have output if instead of (qqq), unless
> quote it another special case.

-- 
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