Created
July 13, 2015 17:14
-
-
Save favila/d65845ad2560fd744d65 to your computer and use it in GitHub Desktop.
Conditionally assoc values of a source map to a target map.
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 cond-assoc-from | |
"Using a source ILookup (map, vector, etc) and a target IAssoc (map), for each | |
clause bind the value of source at given source-key to a binding expression | |
and assoc the target-expression (evaluated with bindings) to the target under target-key. | |
If the source-key's value is nil, skip the clause. Example: | |
(cond-assoc-from {:a [1 2]} {} | |
[a-1 a-2] :a :A (inc a-2) | |
b :b :B (inc b)) | |
;=> {:A 3}" | |
[source target & clauses] | |
(assert (zero? (rem (count clauses) 4)) | |
"Incomplete clause. Clauses must be binding, source-key, target-key, target-expression.") | |
(let [source-sym (gensym "src_") | |
target-sym (gensym "tgt_")] | |
`(let [~source-sym ~source | |
~target-sym ~target | |
~@(mapcat (fn [[binding skey tkey tval]] | |
`(~target-sym (if-some [~binding (get ~source-sym ~skey)] | |
(assoc ~target-sym ~tkey ~tval) | |
~target-sym))) (partition 4 clauses))] | |
~target-sym))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment