Clojure映射中的默认值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Clojure映射中的默认值相关的知识,希望对你有一定的参考价值。

我有一个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")的缺点是我们无法再将falsenil作为值传递,在这种情况下始终使用默认值。

答案

(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")

被读者扩展为

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

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

(:title opts "Default title")

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

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

val = hash[:key] || :default

因此,不熟悉某些Clojure习语的人可能更容易解析第一个表达式。

另一答案

这是地图销毁时使用的: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
nil

以上是关于Clojure映射中的默认值的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 clojure 模式库在映射中使用字符串键验证值

在 Clojure 中将元组数组转换为哈希映射

如何在 clojure 中映射很少使用的状态?

如何在 Clojure 中为函数参数创建默认值

从clojure中的普通lisp替换(null x)函数的惯用方法

Clojure 交换!在 let 绑定中的 map 函数内不起作用