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