【问题标题】:Why does (or <falsey value> <falsey value>) return the final value in Clojure?为什么 (or <falsey value> <falsey value>) 在 Clojure 中返回最终值?
【发布时间】:2015-03-31 18:27:48
【问题描述】:

我开始使用 Clojure 并注意到虽然 Clojure 的 or 行为据说返回第一个真值,但将两个假值传递给 or 只返回第二个值:

user=> (or false false)
false

user=> (or false nil)
nil

我的经验主要是在 Python 中,其中

>>> False or False
False

这些不是类似的吗?我知道这是http://clojuredocs.org/clojure.core/or 的预期行为,并按照建议调查http://clojuredocs.org/clojure.core/if,但仍不清楚为什么会这样。

【问题讨论】:

  • 嗯,在 Python 中你使用or,而不是|| 是按位的。 Python 中的 or 的行为类似于 Clojure 中的 or(不幸的是)。
  • 对,这太草率了。谢谢!
  • 我刚刚注意到这里的“布尔”标签 - clojure 中的 or 绝不是布尔值
  • 在虚假情况下我想不出任何东西,但是对于真实值,有像 ... (let x [or x default-value-for-x] body-using-x)... 这样的成语依赖于 or 返回表达式的值而不是 true

标签: clojure boolean


【解决方案1】:

我认为文档字符串很清楚。它从不承诺返回 false - 如果没有其他参数,则仅返回最后一个参数。

user=> (doc or)
-------------------------
clojure.core/or
([] [x] [x & next])
Macro
  Evaluates exprs one at a time, from left to right. If a form
  returns a logical true value, or returns that value and doesn't
  evaluate any of the other expressions, otherwise it returns the
  value of the last expression. (or) returns nil.
nil

另外,我不知道你从哪里得到or 接受两个参数的想法。

user=> (or nil false false false 1 (println "this is not printed"))
1
user=> (or nil false)
false
user=> (or true)
true
user=> (or)
nil

【讨论】:

  • 谢谢——我只是错过了,因为我在寻找不同的描述(比如为什么会这样)。我不认为or 需要两个参数,但为了简单起见,使用了该示例。
  • 具有短路和任意参数计数的广义or可以追溯到lisp的古老历史,它仍然存在,因为它很有用。
  • 我的困惑部分源于我不知道如何区分最后一个参数是因为它是真的而返回的场景和它是因为它是最后一个参数而返回的场景。
  • 最后一个参数永远不会返回,因为它是真的。如果您查看源代码,如果剩下一个参数,则始终评估并返回该参数。
【解决方案2】:

我怀疑它这样做是因为它更快。

请记住,or 是一个宏,它在编译时构造了一个级联的if 表单,当它到达一个参数时终止,在(构造一个表单)中只是返回那个争论。

例如,

(or 1 2 3)

... 展开成等价于

的东西
(if 1 1 (if 2 2 3))

如果我们包含确保表达式只计算一次的 jiggery-pokery,则扩展看起来更像这样:

(let [__auto__ 1]
  (if __auto__
    __auto__
    (let [__auto__ 2]
      (if __auto__
        __auto__
        3))))

... 其中__auto__ 是一些符号,不会与or 的参数中使用的任何符号发生冲突。

您可以在source code 中找到完整的故事。

【讨论】:

    【解决方案3】:

    实际上,很多语言的行为与 javascript、php 和 python 相同。它甚至是 javascript 中的一个约定,为函数参数myval = myval or defaultValue; 提供默认值。在 php 中人们会写类似do_something() or die(); 的东西。 or 不仅仅适用于动态语言中的布尔值。我也花了很长时间才意识到这一点。

    【讨论】:

      猜你喜欢
      • 2018-02-23
      • 2021-12-10
      • 2015-06-24
      • 2022-06-14
      • 2019-11-24
      • 2018-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多