我有一个clojure地图。将其命名为opts。我知道有两种方法可以从这个映射中获取值,这样如果没有键,就可以获得一些默认值:
(let [opts {}
title-1 (or (:title opts) "Default title")
title-2 (:title opts "Default title")]
(println title-1 title-2))我看到一些库(quil,incanter)在or中使用第一种方法。在我看来,第二种方法更简洁、更干净。第一种方法有优势吗?
使用(or (:title opts) "Default value")的缺点是我们不能再将false和nil作为值传递,在这种情况下总是使用默认值。
发布于 2012-12-11 17:43:20
(or (:key hash) default)和(:key hash default)之间的一个重要区别是前者仅在必要时评估default。在后一种情况下,总是对其求值。因此,如果default的计算代价很高,则应该使用or。
当您的散列包含在布尔上下文中为假的值时,另一个区别变得很明显。在这些值的情况下,(or (:key hash) default)将被计算为default,而不是您期望的false或nil。与or表达式相反,(:key hash default)将产生正确的结果。顺便说一句,在将nil作为值存储在散列中之前,请三思。
好吧,这些都是重要的区别。现在让我们转到次要的部分。
(or (:title opts) "Default title")由读取器扩展为
;; Redacted for the sake of brevity.
(let* [x (:title opts)]
(if x
x
"Default title"))可以说,它比简单地评估效率要低
(:title opts "Default title")当然,如果没有任何基准,很难估计速度的差异,但我认为它应该是边际的。
另一方面,乍一看,对于不习惯(:key hash :default)习惯用法的人来说,(or (:key hash) :default)似乎更容易理解。考虑一下来自其他语言的程序员。例如,在Ruby中,处理不存在的散列元素的典型方法是
val = hash[:key] || :default因此,对于不习惯某些Clojure习惯用法的人来说,第一个表达式可能更容易解析。
发布于 2019-10-05 21:19:53
这就是在进行地图析构时使用:or键的原因。
(defn f [{:keys [title-1 title-2] :as opts
:or {title-1 "default-1" title-2 "default-2"}}]
(println opts)
(println title-1)
(println title-2))这给了你
> (f {})
{}
default-1
default-2
nil
> (f {:title-1 "foo"})
{:title-1 foo}
foo
default-2
nil
> (f {:title-2 "bar"})
{:title-2 bar}
default-1
bar
nil
> (f {:title-1 "foo" :title-2 "bar"})
{:title-1 foo, :title-2 bar}
foo
bar
nilhttps://stackoverflow.com/questions/13817244
复制相似问题