On Sat, Apr 10, 2010 at 10:22 AM, Douglas Philips <d...@mac.com> wrote: > On 2010 Apr 9, at 9:04 PM, Per Vognsen wrote: > >> On Sat, Apr 10, 2010 at 7:48 AM, Douglas Philips <d...@mac.com> wrote: >>> >>> Odd: >>> user=> (binding [m1 (fn [a b] (println "m1 from binding" a b))] >>> (eval '(if true (m1 "true" "here") (m1 "false" >>> "there")))) >>> m1 from binding true here >>> m1 from binding false there >>> nil > >> >> That doesn't even run for me on HEAD. But I can guess what's going on >> from a small experiment: >> > > ?? That was presupposing the defmacro m1 from the earlier email. > I'm running 1.1.0 from macports, not HEAD.
I know. That wasn't the problem. It throws an arity error exception when m1 is invoked as a macro. >> The difference between a function and a macro is a flag in the >> metadata flag. Metadata is a feature of the container (the var) rather >> than the contents. So when you rebind a var that was created by >> defmacro, you retain the macrohood of the root. That means it's >> invoking your function as a macro at compile time rather than as a >> function at run time. > > Now that makes sense. How could I have figured that out from the > documentation? > [snip] > > Ok, so another example: > user=> (defmacro foo [] (println "invoking foo") '(list 1 2 3)) > #'user/foo > user=> (if true (foo) (foo)) > invoking foo > invoking foo > (1 2 3) > > so far, so good. > > user=> (binding [foo (fn [] (println "binding foo") '(list 4 5 6))] > (if true (foo) (foo))) > invoking foo > invoking foo > (1 2 3) Not surprising. The binding form deals with dynamic run-time extents. Here you are treating it like Common Lisp's macrolet. When you explicitly wrap the inner expression in eval, then the run time of the outer code effectively becomes the compile time of the inner code, so that's why your earlier code triggered this surprising behavior. > vs: > > user=> (defn foo [] (println "defn foo") '(1 2 3)) > #'user/foo > user=> (if true (foo) (foo)) > defn foo > (1 2 3) > > > so somehow defn is doing more than rebinding at the top level; [snip] > > Given that definition, shouldn't my defn'ing foo after having defmacro'd foo > have left foo flagged as a macro, since def is reusing the existing var? Trust the code. If you look at DefExpr.emit(), you can see that it sets the metadata from scratch based on the metadata attached to the name symbol. This is what you would expect anyway, or redefinition would be very weird. -Per -- 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 To unsubscribe, reply using "remove me" as the subject.