带谓词的Clojure默认值

时间:2017-08-08 10:42:34

标签: design-patterns clojure

常见模式是在某些值不满足谓词时提供默认值。当值绑定到名称时,编写此类模式的好方法是什么?

目前我使用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"})

但是我认为有人必须早点考虑过这个问题,那么有没有一种既定的方法呢?

2 个答案:

答案 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 []}

默认情况下,它们被重复使用,以上是一种简单的方法。