Skip to content

Instantly share code, notes, and snippets.

@favila
Created July 13, 2015 17:14
Show Gist options
  • Save favila/d65845ad2560fd744d65 to your computer and use it in GitHub Desktop.
Save favila/d65845ad2560fd744d65 to your computer and use it in GitHub Desktop.
Conditionally assoc values of a source map to a target map.
(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