9

根据http://hyperpolyglot.org/lisp,Clojure 中唯一的谎言是falseand nil。确实,令人惊讶的是,(Boolean. false)这不是假的:

user=> (if (Boolean. false) 1 2)
1
user=> (not (Boolean. false))
false
user=> (false? (Boolean. false))
false

另一方面,它在某种程度上错误的:

user=> (class false)
java.lang.Boolean
user=> (= false (Boolean. false))
true

这是相当违反直觉的。这种行为是有原因的还是只是被忽视了?

4

3 回答 3

13

您可以在http://clojure.org/special_forms#if找到解释。

阅读整段内容很好,但这里是摘录的关键部分,重点补充说:

[...] Clojure 中的所有 [...] 条件都基于相同的逻辑,即nilfalse构成逻辑错误,而其他所有内容都构成逻辑真,并且这些含义始终适用。[...]请注意,如果不测试 java.lang.Boolean 的任意值,则仅测试奇异值 false(Java 的 Boolean.FALSE),因此如果您要创建自己的盒装布尔值,请确保使用 Boolean/valueOf 和不是布尔构造函数。

比较

System.out.println(Boolean.valueOf(false) ? true : false);  // false
System.out.println(new Boolean(false)     ? true : false);  // false

user=> (if (Boolean/valueOf false) true false)
false
user=> (if (Boolean. false) true false)
true

因此,(Boolean. false)既不是nil也不是false,就像(Object.)既不是nil也不是false。正如@Chiron 指出的那样,无论如何使用它都是不好的做法。

至于(= false (Boolean. false))是否属实,我认为@looby 的解释是正确的:由于=依赖于 Java 的equals方法,因此 Clojure 中条件的特殊语义不适用,布尔相等将与 Java 中一样。

于 2013-09-08T10:37:13.287 回答
5

永远不要调用 (Boolean.true) 或 (Boolean."true")。不要创建布尔类的任何实例。这两种形式真的很邪恶。

这不是 Clojure 的问题,实际上是 Java 的问题。

布尔值只有两个可能的值:Java 已经提供的 true 或 false。构造函数给您一种错觉,即您可以创建一个新的 Boolean 类实例,该实例可以表现为 Boolean 但它不会。

如果您真的想从 String 或 boolean 创建一个 Boolean 实例,请使用 Boolean 类的 valueOf() 方法。

(Boolean/valueOf "true")
(Boolean/valueOf  true)

Boolean.html#valueOf(boolean)

于 2013-09-07T19:34:55.923 回答
3

我认为发生这种情况的原因是Clojure 的 =使用了 Java 的equals方法。就是(= x y)这样x.equals(y)。所以false被迫进入(Boolean. false)引擎盖下的比较。

请注意,这并不意味着它(Boolean. false) 是 false或它与 false '相同',只是当false(Boolean. false)使用equals被认为相等的方法进行比较时。

于 2013-09-07T19:59:22.520 回答