How can you get a map of the local variables defined using let?
(let [foo 1] (println (get (get-thread-bindings) "foo")))
; prints nil
Is there another function that does this? Or is there a way to extract the variables from the get-thread-bindings map? Any solution should work with nested let statements as well.
As pointed out in the link in the comments, there's a special &env
variable available inside defmacro
. Per the documentation:
Two special variables are available inside defmacro for more advanced usages:
- &form - the actual form (as data) that is being invoked
- &env - a map of local bindings at the point of macro expansion. The env map is from symbols to objects holding compiler information about that binding.
You can use this to write a macro that will expand to give you a mapping of local bindings at the point where the macro is expanded:
(defmacro get-env
[]
(into {} (for [k (keys &env)]
[(name k) k])))
This expands as a map of symbol name (name k)
to symbol k
for all local bindings (keys &env)
which, when evaluated, will give a map of symbol name to current binding for the symbol.
user> (get-env) ; => {}
user> (let [a 1] (get-env)) ; => {"a" 1}
user> (let [a 1 b 2]
(let [b 3 c 4] (get-env))) ; => {"c" 4, "b" 3, "a" 1}
It even works with function parameters:
user> (defn foo [x] (let [y 1] (get-env)))
user> (foo 2) ; => {"y" 1, "x" 2}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With