2017-08-08 51 views
1

常见模式是如果某个值不符合谓词,则会提供默认值。当值为而不是绑定到某个名称时,编写这种模式的好方法是什么?带谓词的Clojure默认值

目前我使用let表达式。例如,如果我想为空字符串的默认值我可能会写类似:

(let [value {:a "foo"}] 
    (if (:a value) value {:a "bar"})) 

不过,我觉得这样就可以简化成更接近匹配falsy值相同proceduce。

(or value default) 

我已经考虑创建一个函数,它是:

(defn or-default [pred value default] 
    (if (pred value) value default)) 

随着其上面的例子就变成:

(or-default :a {:a "foo"} {:a "bar"}) 

不过,我认为一定有人想过这个早些时候,那么是否有一个既定的方法?

+0

我使用'(或默认值)'。 –

+0

@ErwinRooijakkers @ErwinRooijakkers我的问题是为其他谓词,然后简单地truthy/falsy – user3792713

+0

,这将是你需要的东西:'(或(和(pred值)的价值)默认)'如果你想避免使用'if' – leetwinski

回答

3

你可以用解构解决这个

(let [{:keys [a] :or {a "default"}} {:b "foo"}] a) 
;; => default 

此外,get,您可以提供一个默认值:

(get :a {:b "foo"} "default") 
;; => default 

还与关键字访问

(:a {:b "foo"} "default") 
;;=> default 
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 []} 

它是在它们被重复使用的默认值的性质,和上述是一种简单的方法来做到:其执行特定的功能的默认值 这个。