Thursday, 16 July 2009

Fragile predicates with Java's booleans

Interoperability with the JVM is a wonderful thing but it can be the root of some surprises. The following seemingly innocuous Clojure snippet produces a surprising result:

user=> (if (Boolean. false) "true" "false")
"true"

Specifically, we used a predicate that appears to be false but the true branch of the if expression was taken. This occurs because Clojure uses a boxed representation of booleans that is incompatible with Java's. Combined with Clojures dynamic typing, this causes Java's false to be interpreted as not Clojures false and, therefore, true.

The solution is to box Java booleans in order to obtain a Clojure boolean:

user=> (if (boolean (Boolean. false)) "true" "false")
"false"