Clojure / Script是否提供一种从参数加上填充的默认值(如果在调用中未提供键的情况下)构建非结构化映射的方法?
请考虑以下示例(快速浏览并不一定能完成代码所暗示的工作)。 Clojure是否提供一种使用这四个键和调用者或默认值创建映射prompt
的方法。我讨厌认为我必须再重复两次这些键名才能得到我想要的。
(re-frame/reg-event-db
:open-prompt
(fn [db [_ {title :title
text :text
label-yes :label-yes
label-no :label-no
:or {title "Confirm"
text "Are you sure?"
label-yes "Ok"
label-no "Cancel"}
:as prompt}]]
(-> db
(update :state conj :modal-prompt)
(assoc :prompt prompt))))
[C0复习后,我认为Clojure并没有提出更简便的方法。
但是只是出于好奇,我想知道解构生成的代码是什么,因为我希望它依赖于宏。让我们考虑这个玩具示例:
official documentation page about destructuring
因此,您可以看到,在宏扩展之后,允许指定默认值的(def my-map {:text "Some text"})
(let
[{title :title
:or {title "Confirm"}
:as prompt} my-map]
(str "I got " title " from " prompt))
;; => "I got Confirm from {:text \"Some text\"}"
(macroexpand '(let
[{title :title
:or {title "Confirm"}
:as prompt} my-map]
(str "I got " title " from " prompt)))
;; => (let*
;; [map__12555
;; my-map
;; map__12555
;; (if
;; (clojure.core/seq? map__12555)
;; (clojure.lang.PersistentHashMap/create
;; (clojure.core/seq map__12555))
;; map__12555)
;; prompt
;; map__12555
;; title
;; (clojure.core/get map__12555 :title "Confirm")]
;; (str "I got " title " from " prompt))
机制依赖于:or
。
在此特定示例中,clojure.core/get
受title
格式的影响。这是避免重复(clojure.core/get map__12555 :title "Confirm")
变量的一种方法,但这值得吗?
您还可以检查title
以获得有关它的完整详细信息,但是我个人觉得很难处理^^'。
我喜欢制作所有默认值的映射,然后使用source code of the destructuring macro或类似方法将用户提供的值融合到默认值的映射中。例如:
into
此处(ns tst.demo.core
(:use tupelo.core tupelo.test) )
(def vals-default {:a 1 :b 2})
(defn apply-defaults
[arg]
(let [vals (glue vals-default arg)] ; or use `into`. Last one wins, so put defaults first
(with-map-vals vals [a b]
(newline)
(spyx a)
(spyx b))
vals))
(dotest
(is= (apply-defaults {}) ; no inputs => all default values
{:a 1, :b 2})
(is= (apply-defaults {:a 100}) ; some inputs => partial defaults
{:a 100, :b 2})
(is= (apply-defaults {:a 100, :b 200}) ; all inputs => no defaults used
{:a 100, :b 200}))
类似于glue
,但具有更多的错误检查。我们还使用into
来破坏地图,其重复次数少于本机Clojure的破坏(tupelo.core/with-map-vals
则相反)。
输出为:
vals->map