[英]Clojure default value with predicate
A common pattern is to provide a default value if some value does not fulfill a predicate. 常见的模式是,如果某些值不满足谓词,则提供默认值。 What is a good way of writing such a pattern when the value is not bound to a name?
当值未绑定到名称时,写这种模式的好方法是什么?
Currently I use a let expression. 目前,我使用let表达式。 If for example I would like to provide a default value for empty strings I might write something like:
例如,如果我想为空字符串提供默认值,我可能会写类似:
(let [value {:a "foo"}]
(if (:a value) value {:a "bar"}))
However, I feel like this could be simplified to closer match the same proceduce for falsy values. 但是,我认为可以简化此过程以更紧密地匹配伪造值的相同过程。
(or value default)
I have considered creating a function that does it: 我考虑过创建一个可以做到的函数:
(defn or-default [pred value default]
(if (pred value) value default))
With which the above example would become: 上面的示例将变为:
(or-default :a {:a "foo"} {:a "bar"})
However I assume someone must have thought about this earlier, so is there an established way? 但是我认为一定有人早些考虑过,所以有没有确定的方法?
You can use destructuring to solve this 您可以使用解构来解决此问题
(let [{:keys [a] :or {a "default"}} {:b "foo"}] a)
;; => default
Also, get
lets you provide a default value: 另外,使用
get
可以提供默认值:
(get :a {:b "foo"} "default")
;; => default
Also works with keyword access 也适用于关键字访问
(:a {:b "foo"} "default")
;;=> default
For supplying default values for map keys, the function you are looking for is essentially merge
with the defaults as the first argument: 为了提供映射键的默认值,您要查找的函数实际上与默认值
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}
We can package this as function map-defaults
that, given the defaults, returns a function that fills them in: 我们可以将其打包为
map-defaults
函数,给定默认值,该函数将返回一个将其填充的函数:
(defn map-defaults [defaults]
(partial merge defaults))
We can use this to create functions that perform particular 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 []}
It is in the nature of defaults that they are used repeatedly, and the above is an easy way to do this. 默认情况下,重复使用它们是自然的,上面是实现此目的的简便方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.