Created
August 22, 2015 22:04
-
-
Save rauhs/909d1af8f4ac1dc73e21 to your computer and use it in GitHub Desktop.
Macro: Assoc a map only if the key is nil. Does NOT evaluate the value unless it is nil.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defmacro assoc-if-nil | |
"Takes a map as the first argument and a succession of key value pairs that | |
are used to set the key to value if the key of the map is nil. The value part | |
is only evaluated if the key is nil (thus different semantics to (merge)). | |
Example: | |
(assoc-if-nil {:a {:b :set}} | |
[:a :b] :non-def | |
[:a :c] :non-def | |
:d :non-def) | |
;; =>{:a {:b :set, :c :non-def}, :d :non-def}" | |
[m & clauses] | |
(assert (even? (count clauses))) | |
(let [g (gensym) | |
get-fn (fn[kork] (if (vector? kork) `get-in `get)) | |
assoc-fn (fn[kork] (if (vector? kork) `assoc-in `assoc)) | |
pstep (fn [[kork v]] `(if (~(get-fn kork) ~g ~kork) | |
~g | |
(~(assoc-fn kork) ~g ~kork ~v)))] | |
`(let [~g ~m ;; avoid double evaluation | |
~@(interleave (repeat g) (map pstep (partition 2 clauses)))] | |
~g))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment