说我有这个fn
(let [{:keys [a b c d] :as params} {:a 1 :b 1 :c nil :d nil}]
(cond-> params
a (update :b inc)
(= b 2) (assoc :c "here")
c (assoc :d "here")))
我会得到什么
;;=> {:a 1, :b 2, :c nil, :d nil}
我想要什么:
;;=> {:a 1, :b 2, :c "here", :d "here"}
可能的语法:
(let [params {:a 1 :b 1 :c nil :d nil}]
(cond$-> params
(:a $) (update :b inc)
(= (:b $) 2) (assoc :c "here")
(:c $) (assoc :d "here")))
此解决方案或类似解决方案是否已在某处实施?
答案 0 :(得分:3)
这里有一个简单的实现方式:
(defmacro cond$->
([value] value)
([value cond body & clauses]
(assert (even? (count clauses)))
`(cond$-> (let [~'$ ~value]
(if ~cond (-> ~'$ ~body) ~'$))
~@clauses)))
基本上,它只是在第一个条件和主体上创建一个表单。如果条件匹配,则除非使用原始值,否则下一个cond$->
调用的值将为body
。它使用递归来处理所有子句。
通常,最好让用户选择将用于绑定值的符号:
(defmacro cond-as->
([value sym] value)
([value sym cond body & clauses]
(assert (even? (count clauses)))
`(cond-as-> (let [~sym ~value]
(if ~cond ~body ~sym))
~sym
~@clauses)))
(let [params {:a 1 :b 1 :c nil :d nil}]
(cond-as-> params $
(:a $) (update $ :b inc)
(= (:b $) 2) (assoc $ :c "here")
(:c $) (assoc $ :d "here")))
答案 1 :(得分:1)
我可以看到这可能有用。您可以找到my take on it here:
(let [params {:a 1 :b 1 :c nil :d nil}]
(cond-it-> params
(:a it) (update it :b inc)
(= (:b it) 2) (assoc it :c "here")
(:c it) (assoc it :d "again")))
;=> {:a 1, :b 2, :c "here", :d "again"}
实施:
(defmacro cond-it->
[expr & forms]
(let [num-forms (count forms)]
(when-not (even? num-forms)
(throw (IllegalArgumentException. (str "num-forms must be even; value=" num-forms)))))
(let [cond-action-pairs (partition 2 forms)
cond-action-forms (for [[cond-form action-form] cond-action-pairs]
`(or (when ~cond-form) ~action-form)) ]
`(it-> ~expr ~@cond-action-forms)))