Do you know about macroexpand?

user=> (defmacro m1 [v] `(def (symbol ~v)))
#'user/m1
First argument to def must be a Symbol
user=> (macroexpand '(m1 "foo"))
(def (clojure.core/symbol "foo"))
user=> (defmacro m2 [v] `(def ~(symbol v)))
#'user/m2
user=> (macroexpand '(m2 "foo"))
(def foo)

The trick here is that you need to convert v into a symbol when the macro
is expanded, not at runtime.

On Oct 2, 2020 at 3:37:52 PM, Rostislav Svoboda <rostislav.svob...@gmail.com>
wrote:

> I have a problem with `def` in macros. I'd like to create a bunch of
> following definitions:
>
> (def foo "FOO")
> (def bar "BAR")
> (def baz "BAZ")
>
> So I wrote a macro:
>
> user=> (defmacro def-stuff [v] `(def (symbol ~v)
> (clojure.string/upper-case ~v)))
> #'user/def-stuff
>
> And I'd like to do map this macro over a vector of strings:
>
> user=> (map (fn [n] (def-stuff n)) ["foo" "bar" "baz"])
> Syntax error compiling def at (REPL:1:14).
> First argument to def must be a Symbol
>
> A little check indicates that everything should be fine:
> user=> (symbol? (symbol "foo"))
> true
>
> but it is not:
> user=> (def (symbol "foo") "FOO")
> Syntax error compiling def at (REPL:1:1).
> First argument to def must be a Symbol
>
> ???
> Interestingly enough:
>
> user=> (defmacro def-stuff [v] `(def v (clojure.string/upper-case ~v)))
> #'user/def-stuff
> user=> (map (fn [n] (def-stuff n)) ["foo" "bar" "baz"])
> (#'user/v #'user/v #'user/v)
>
> Strangely enough a `v` gets (re)defined.
>
> To me it looks like the lexical-binding of macro-parameters is ignored if
> there's a `(def <macro-param> ...)` inside this macro.
>
> Can anybody explain what's going on here please? Thanks.
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/clojure/CAEtmmex6Kn%3DQ8AZ-AyYoZLpYVu7%2BWnX3u7vQBgydiA%2B1jUt9Rw%40mail.gmail.com
> <https://groups.google.com/d/msgid/clojure/CAEtmmex6Kn%3DQ8AZ-AyYoZLpYVu7%2BWnX3u7vQBgydiA%2B1jUt9Rw%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/CAKL9L2kXoG-9psgnbNKtdRBsAW3si_bRCDFpwB50thmM610MKg%40mail.gmail.com.

Reply via email to