here is an example of a macro that takes a list of alternating names and values, binds them in a let and then saves a map of the bindings that it just created by introducing a symbol called 'locals' that names a map of local-names to local-values.
(defmacro anaphoric-let [alternating-symbols-and-values & body]
`(let [~@alternating-symbols-and-values
names# (quote ~(flatten (partition 1 2 alternating-symbols-and-values)))
values# ~(vec (flatten (partition 1 2 alternating-symbols-and-values)))
~'locals (zipmap names# values#)]
~@body))
any expressions called withing anaphoric-let
will be able to use the values form the locals
name.
user> (anaphoric-let [a 1 b 2 c 3 d 4] [a locals])
[1 {d 4, c 3, b 2, a 1}]
saving the values in a map after defining them with let and before the body is important to prevent multiple execution and the other sins of unhygienic macros.
this map can then be used to make decisions based on the locals:
user> (anaphoric-let [a 1 b 2 c 3 d 4 e "cat"]
(map (fn [[local val]]
(str local " is " (if (number? val) val "woof")))
locals))
("e is woof" "d is 4" "c is 3" "b is 2" "a is 1")
or:
user> (anaphoric-let [a 1 b 2 c 3 d 4 e "cat"]
(println "omg no way!")
(dorun (for [x (vals locals)]
(if (number? x) (println "roar")))))
omg no way!
roar
roar
roar
roar
nil
ps: anaphoic macros are any macro that introduces a name into the code it creates that did not exist in the code passed to it.