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.


Reply via email to