clojure地图中的默认值

Nik*_*zov 13 clojure map

我有一张clojure地图.说出来opts.我知道从这个地图获取值的两种方法,如果没有键获得一些默认值:

(let [opts {}
      title-1 (or (:title opts) "Default title")
      title-2 (:title opts "Default title")]
  (println title-1 title-2))
Run Code Online (Sandbox Code Playgroud)

我看到一些库(quil,incanter)使用第一种方法or.在我看来,第二种方法更简洁,更清洁.第一种方法有优势吗?
使用的缺点(or (:title opts) "Default value")是我们不能再传递falsenil作为值,在这种情况下总是使用默认值.

Jan*_*Jan 22

两者之间的关键区别在于(or (:key hash) default),(:key hash default)前者default仅在必要时进行评估.在后一种情况下,它总是被评估.因此,or如果评估default费用昂贵,您应该使用.

当您的哈希包含布尔上下文中的false值时,另一个区别变得明显.在这种情况下,(or (:key hash) default)将评估default代替您falsenil您期望的值.与or表达式相反,(:key hash default)将产生正确的结果.作为旁注,在将nil值作为值存储在哈希中之前请三思而后行.

好吧,那些是重要的区别.现在让我们转向次要的.

(or (:title opts) "Default title")
Run Code Online (Sandbox Code Playgroud)

由读者扩展到

;; Redacted for the sake of brevity.
(let* [x (:title opts)]
  (if x
    x
    "Default title"))
Run Code Online (Sandbox Code Playgroud)

可以说,它比简单评估效率低

(:title opts "Default title")
Run Code Online (Sandbox Code Playgroud)

当然没有任何基准,很难估计差异是速度,但我认为它应该是微不足道的.

另一方面,(or (:key hash) :default)对于不(:key hash :default)熟悉习语的人来说,乍一看似乎更容易理解.考虑来自其他语言的程序员.例如,在Ruby中,处理散列的非存在元素的典型方法是

val = hash[:key] || :default
Run Code Online (Sandbox Code Playgroud)

因此,第一个表达可能更容易被不习惯某些Clojure成语的人解析.

  • 我完全不同意你应该始终保持一致:每种风格偶尔都是必要的.如果默认表达式的计算成本非常高,你应该使用`或'样式,当`nil`或`false`是有效值时你应该使用默认值,你需要区分"Nothing there"和"false or nil"那里". (2认同)