根据http://hyperpolyglot.org/lisp,Clojure中唯一的谎言是false
和nil
。确实,令人惊讶的是,(Boolean. false)
并非虚假:
user=> (if (Boolean. false) 1 2)
1
user=> (not (Boolean. false))
false
user=> (false? (Boolean. false))
false
另一方面,它以某种方式是 false:
user=> (class false)
java.lang.Boolean
user=> (= false (Boolean. false))
true
这是违反直觉的。这种行为有原因还是被忽视了? Clojure中的其他Java数据类型是否也会发生类似的事情?它在ClojureScript和ClojureCLR中是否相同,或者它是否特定于JVM版本?其他JVM Lisps,如Kawa或ABCL,是否表现出类似的行为(如果他们使用Java布尔值)?
答案 0 :(得分:12)
您可以在http://clojure.org/special_forms#if找到解释。
阅读整个段落是件好事,但这里的重点是摘录,重点是:
[...] Clojure中的所有条件都基于相同的逻辑,即 nil 和 false 构成逻辑错误,以及所有内容否则构成逻辑真理,这些意义贯穿始终。 [...] 请注意 if 不测试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一样。
答案 1 :(得分:5)
不要永远调用(Boolean。true)或(Boolean。“true”)。不要创建任何布尔类的实例。这两种形式真的很邪恶。
这不是Clojure的问题,实际上它是Java的问题。
布尔值只有两个可能的值:true或false,它们已由Java提供。构造函数给你一种错觉,你可以创建一个布尔类的新实例,它可以表现为布尔但不会。
如果你真的想从String或boolean创建一个布尔实例,那么使用Boolean类的valueOf()方法。
(Boolean/valueOf "true")
(Boolean/valueOf true)
答案 2 :(得分:3)
我认为发生这种情况的原因是Clojure's =使用Java的equals
方法。所以(= x y)
就像x.equals(y)
。因此,false
在引擎盖下的比较中被强制导入(Boolean. false)
。
请注意,这并不意味着(Boolean. false)
为假或与false 相同,只是在false
时(Boolean. false)
使用equals
方法对它们进行比较。