This macro returns the values of the "magic" &env
as a map, so that
(let [xyz "ZYX"] (get-env))
returns {xyz "ZYX"}
, where the key is a Symbol.
(defmacro get-env []
(let [ks (keys &env)]
`(zipmap '~ks [~@ks])))
The expression '~ks
evaluates the ks
into Symbols at the macro-expansion phase (right?), but then quotes the expansion, so that the Symbols don't get evaluated into their values ("ZYX"
in our example), but rather stay as Symbols (xyz
). Is that right?
About [~@ks]
: It evaluates ks
into an seq of Symbols at the macro-expansion phase (right?) (and splices them and forms a vector with []
). But how does that allow these Symbols to get further evaluated into their values ("ZYX"
in our example) -- is there a second evaluation step, applied immediately after the first?
Another variant is
(defmacro local-env [] (->> (keys &env)
(map (fn [k] [(list 'quote k) k])) (into {})))
Your macro takes all the keys from the env. Then it uses the keys (a list of symbols) to zip both the list of keys with spliced symbols inside a vector. So what you get from
(let [x 42]
(get-env))
is
(let [x 42]
(zipmap '(x) [x]))
This is a compile-time transformation of your code (the whole point of macros). The resulting code at runtime will use the 42 from the bound x.