"foo = bar || baz" 的Clojure惯用语是什么?

19

我想提供一个可以被覆盖的默认值。我知道可以使用三元运算符,例如:

(def foo (if (not (nil? bar)) bar baz))

但是在Clojure中,肯定有更符合习惯的方式来表达“如果bar为nil,则使用baz”。

有什么建议吗?

3个回答

34

除非barnilfalse,否则将其分配给baz

(def foo (or bar baz))

编辑

如果你想要精确地检查 nil ,你可以稍微优化你的原始代码,像这样:

(def foo (if (nil? bar) baz bar))

我认为,这是最短的可能方式,虽然不是惯用语。


这很棒,可以解决我在代码中遇到的问题,但我也想知道在这种情况下区分nilfalse的习语。 - Josh Glover
1
@JoshGlover 嗯,我不确定是否有一个特殊的习语来描述这个问题,但是如果你交换 barbaz 的位置,像这样 (if (nil? bar) baz bar)),你就可以摆脱 not,而且它几乎不会变得更短。 - bereal
很好的观点,确实非常棒。谢谢!如果您更新您的答案以展示这种方式,我会接受它。 - Josh Glover

4
您的问题并没有特别提到多个变量,但如果您想要为多个变量设置默认值,惯用的方法是在带有:or默认值的map上使用解构。
例如,考虑以下接受map参数m的函数,预期map具有:a:b:c键,但如果未提供:b和/或:c,则将从:or子句中获取默认值。
(defn foo [m]
    (let [{:keys [a b c], :or {b 100 c 200}} m]
      (println "a:" a)
      (println "b:" b)
      (println "c:" c)))

user> (foo {:a 1 :b 2})
a: 1   ; no default, use supplied value
b: 2   ; value supplied, default ignored
c: 200 ; no value supplied, use default from :or
nil

2

fnil也是一个选项:

user> (def default-to (partial fnil identity))
#'user/default-to

user> (let [bar :foo
            baz :default]
        ((default-to baz) bar))
:foo

user> (let [bar nil
            baz :default]
        ((default-to baz) bar))
:default

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接