Идиоматического способу установить значения по умолчанию в Clojure является со слиянием:слияния, чтобы установить значения по умолчанию, но потенциально дорогостоящие функции
;; `merge` can be used to support the setting of default values
(merge {:foo "foo-default" :bar "bar-default"}
{:foo "custom-value"})
;;=> {:foo "custom-value" :bar "bar-default"}
В действительности, однако, часто значения по умолчанию не являются простым, но постоянными вызовами функций. Очевидно, я хотел бы избежать вызова функции, если она не будет использоваться.
До сих пор я делаю что-то вроде:
(defn ensure-uuid [msg]
(if (:uuid msg)
msg
(assoc msg :uuid (random-uuid))))
и применить мои ensure-*
функции, такие как (-> msg ensure-uuid ensure-xyz)
.
Что было бы более идиоматичным способом сделать это? Я имею в виду что-то вроде:
(merge-macro {:foo {:bar (expensive-func)} :xyz (other-fn)} my-map)
(associf my-map
[:foo :bar] (expensive-func)
:xyz (other-fn))
Это хорошая идея, но страдает от последующего вызова 'force' на протяжении всего кода приложения, которое я Мне бы хотелось избежать. Я написал макрос, который очень хорошо работает для моего варианта использования. Cheers & Thanks – ClojureMostly
Хорошо. Тем не менее, различная семантика - ваше решение оценивает, не указано ли значение на карте, с задержкой оно только оценивает, будет ли значение использоваться. – bsvingen
Btw, это только что создано: https://github.com/Malabarba/lazy-map-clojure – ClojureMostly