(defmacro test-it [sym addend & body] `(let [~sym (+ ~addend 1)] ~@body))
would be the usual preferred Clojure way to handle this sort of situation, but anaphoric is also an option. You can also make macros expand to a def in the caller's namespace this way -- it's how defn works: (defmacro defn [name .........] `(def ~name .........)). But you should only be interning symbols if they make sense to add to the namespace. On Mon, Jul 1, 2013 at 11:30 AM, Baishampayan Ghose <b.gh...@gmail.com>wrote: > +1 totally agree. Eg. clojure.core/with-open > > Sent from phone. Please excuse brevity. > On 1 Jul 2013 20:58, "Gary Trakhman" <gary.trakh...@gmail.com> wrote: > >> Whenever I make a macro like this, I pass the symbol to be captured as an >> argument to the macro. Any collisions would be more explicit and less >> surprising. >> >> >> On Mon, Jul 1, 2013 at 11:21 AM, Baishampayan Ghose <b.gh...@gmail.com>wrote: >> >>> Hi, >>> >>> What you need is called an anaphoric macro (via symbol capture). >>> Clojure makes it hard to do a symbol capture in macros since it >>> qualifies all symbols automatically unless you use the auto gensym >>> feature. This is done for hygiene purposes and to avoid any unintended >>> side-effects. >>> >>> However indeed, it's possible to create such a macro in Clojure. >>> >>> Behold - >>> >>> (defmacro test-it [addend & body] `(let [~'foo (+ ~addend 1)] ~@body)) >>> ;; notice the ~' in front of foo. >>> >>> (macroexpand-1 '(test-it 1 (println foo))) >>> ;=> (clojure.core/let [foo (clojure.core/+ 1 1)] (println foo)) >>> >>> Please apply caution before using this feature; document the symbol to >>> be captured sufficiently. >>> >>> Hope that helps. >>> >>> Regards, >>> BG >>> >>> On Mon, Jul 1, 2013 at 7:44 PM, Sean Johnson <belu...@acm.org> wrote: >>> > Hello, >>> > >>> > If a macro calculates something and wants to make that result >>> available to >>> > the body, what's the right way to do that? So far I've tried these ways >>> > which don't work (this is not really my macro, it's just a simplified >>> > example to demonstrate the issue): >>> > >>> > 1) lexical scope doesn't work, the symbol gets qualified >>> > >>> > (defmacro test-it [addend & body] `(let [foo (+ ~addend 1)] ~@body)) >>> > >>> > => (test-it 3 (println foo)) >>> > CompilerException java.lang.RuntimeException: Can't let qualified name: >>> > fcms.app/foo, compiling:(NO_SOURCE_PATH:1:1) >>> > >>> > => (macroexpand '(test-it 3 (println foo))) >>> > (let* [fcms.app/foo (clojure.core/+ 3 1)] (println foo)) >>> > >>> > >>> > 2) autogen'ed lexical scope doesn't work, the body doesn't know what >>> the >>> > autogen'ed symbol will be called >>> > >>> > (defmacro test-it [addend & body] `(let [foo# (+ ~addend 1)] ~@body)) >>> > >>> > => (test-it 1 (println foo)) >>> > CompilerException java.lang.RuntimeException: Unable to resolve >>> symbol: foo >>> > in this context, compiling:(NO_SOURCE_PATH:1:12) >>> > >>> > => (macroexpand '(test-it 3 (println foo))) >>> > (let* [foo__5755__auto__ (clojure.core/+ 3 1)] (println foo)) >>> > >>> > >>> > 3) an interned var partially works, if the macro and its use are all >>> in one >>> > namespace, but not if not, it fails to intern the var >>> > >>> > (defmacro test-it [addend & body] `(do (def foo (+ ~addend 1)) ~@body)) >>> > >>> > => (test-it 3 (println foo)) >>> > 4 >>> > nil >>> > >>> > => (macroexpand '(test-it 3 (println foo))) >>> > (do (def fcms.app/foo (clojure.core/+ 3 1)) (println foo)) >>> > >>> > => (ns test) >>> > nil >>> > test=> (fcms.app/test-it 3 (println foo)) >>> > CompilerException java.lang.RuntimeException: Can't create defs >>> outside of >>> > current ns, compiling:(NO_SOURCE_PATH:1:1) >>> > >>> > >>> > I don't think my scenario is too unusual, but so far I haven't been >>> able to >>> > find anything about how to best do this. >>> > >>> > It case it helps, the real macro is with-collection and it takes a >>> > collection name, does a lookup and some validation in a DB, then needs >>> to >>> > share the collection's id with the body. >>> > >>> > Cheers, >>> > Sean >>> > >>> > >>> > >>> > -- >>> > -- >>> > 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 >>> > --- >>> > You received this message because you are subscribed to the Google >>> Groups >>> > "Clojure" group. >>> > To unsubscribe from this group and stop receiving emails from it, send >>> an >>> > email to clojure+unsubscr...@googlegroups.com. >>> > For more options, visit https://groups.google.com/groups/opt_out. >>> > >>> > >>> >>> >>> >>> -- >>> Baishampayan Ghose >>> b.ghose at gmail.com >>> >>> -- >>> -- >>> 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 >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to clojure+unsubscr...@googlegroups.com. >>> For more options, visit https://groups.google.com/groups/opt_out. >>> >>> >>> >> -- >> -- >> 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 >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/groups/opt_out. >> >> >> > -- > -- > 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 > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > > > -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.