常见模式是在某些值不满足谓词时提供默认值。当值不绑定到名称时,编写此类模式的好方法是什么?
目前我使用let表达式。例如,如果我想为空字符串提供默认值,我可能会写如下:
(let [value {:a "foo"}]
(if (:a value) value {:a "bar"}))
然而,我觉得这可以简化为更接近匹配相同的程序,用于虚假值。
(or value default)
我考虑创建一个能够实现它的功能:
(defn or-default [pred value default]
(if (pred value) value default))
以上示例将成为:
(or-default :a {:a "foo"} {:a "bar"})
但是我认为有人必须早点考虑过这个问题,那么有没有一种既定的方法呢?
答案 0 :(得分:3)
您可以使用解构来解决此问题
(let [{:keys [a] :or {a "default"}} {:b "foo"}] a)
;; => default
此外,get
可让您提供默认值:
(get :a {:b "foo"} "default")
;; => default
也适用于关键字访问
(:a {:b "foo"} "default")
;;=> default
答案 1 :(得分:1)
为了提供映射键的默认值,您要查找的函数基本上是merge
,默认值为第一个参数:
(merge {:a :a-default} {})
=> {:a :a-default}
(merge {:a :a-default} {:b 1})
=> {:a :a-default, :b 1}
(merge {:b 1, :a 2} {:a :a-default} {:b 1, :a 2})
=> {:b 1, :a 2}
我们可以将其打包为函数map-defaults
,在给定默认值的情况下,返回一个填充它们的函数:
(defn map-defaults [defaults]
(partial merge defaults))
我们可以使用它来创建执行特定默认值的函数:
(def person-default
(map-defaults
{:income 0
:married false
:forenames []}))
(person-default {})
=> {:income 0, :married false, :forenames []}
(person-default {:married true, :income 88000})
=> {:income 88000, :married true, :forenames []}
默认情况下,它们被重复使用,以上是一种简单的方法。