According to http://hyperpolyglot.org/lisp, the only falsehoods in Clojure are false and nil. Indeed, surprisingly enough, (Boolean. false) is not false:
user=> (if (Boolean. false) 1 2)
1
user=> (not (Boolean. false))
false
user=> (false? (Boolean. false))
false
On the other hand, it somehow is false:
user=> (class false)
java.lang.Boolean
user=> (= false (Boolean. false))
true
This is rather counterintuitive. Are there reasons for this behaviour or was it simply overlooked?
You can find the explanation at http://clojure.org/special_forms#if.
It's good to read the whole paragraph, but here's the crucial bit excerpted, emphasis added:
[...] All [...] conditionals in Clojure are based upon the same logic, that is, nil and false constitute logical falsity, and everything else constitutes logical truth, and those meanings apply throughout. [...] Note that if does not test for arbitrary values of java.lang.Boolean, only the singular value false (Java's Boolean.FALSE), so if you are creating your own boxed Booleans make sure to use Boolean/valueOf and not the Boolean constructors.
Compare
System.out.println(Boolean.valueOf(false) ? true : false); // false
System.out.println(new Boolean(false) ? true : false); // false
with
user=> (if (Boolean/valueOf false) true false)
false
user=> (if (Boolean. false) true false)
true
Thus, (Boolean. false) is neither nil nor false, just as (Object.) is neither nil nor false. And as #Chiron has pointed out, it's bad practice to use it anyway.
As for (= false (Boolean. false)) being true, I think #looby's explanation is spot on: Since = relies on Java's equals method, the special semantics of conditionals in Clojure don't apply, and boolean equality will be as it is in Java.
Don't ever and never call (Boolean. true) or (Boolean. "true"). Don't create any instance of Boolean class. Those two forms are really evil.
This isn't an issue of Clojure, actually it is a Java's one.
There are only two possible values for a boolean: true or false which are already provided by Java. The constructors give you the illusion that you can create a new instance of Boolean class that can behave as a Boolean but it won't.
If you really want to create a Boolean instance from a String or a boolean, then use valueOf() method of Boolean class.
(Boolean/valueOf "true")
(Boolean/valueOf true)
Boolean.html#valueOf(boolean)
I think the reason this happens is that Clojure's = uses Java's equals method. So (= x y) is like x.equals(y). So false gets coerced into (Boolean. false) in the comparison under the hood.
Note that this does not mean that (Boolean. false) is false or that it is the 'same' as false, just that when false and (Boolean. false) are compared using the equals method they are considered to be equal.
Related
The book Living Clojure explains that the type nil is treated the same as logical false.
So I expected (false? nil) to return true, which it doesn't. (true? nil) also doesn't. Both return false, which makes me think that Clojure treats nil neither as true nor false.
On the other hand, (not nil) evaluates to true. So I'm a bit confused.
The distinction is testing for logical truth, versus the values themselves.
The values nil and false are treated as logically false in Clojure. All other values are treated as logically true.
The predicates false? and true? test explicitly for the values false and true respectively, as you have noted. These predicates are not often used in Clojure.
According to the documentation of false?:
Returns true if x is the value false, false otherwise.
So the function checks if the parameter equals the value false instead of checking if it is logically false.
In Clojure, all values are either logically true or logically false, so they can be used in conditional expressions. The only logically false values are nil and false.
There are some good answers already.
People sometimes use the terms falsey (nil and false) and truthy (all other values) to describe Clojure values.
It is sometimes handy to coerce values into Boolean true or false. I even wrote a handy function for this:
(defn truthy?
"Returns true if arg is logical true (neither nil nor false); otherwise returns false."
[arg]
(if arg true false))
(defn falsey?
"Returns true if arg is logical false (either nil or false); otherwise returns false. Equivalent
to (not (truthy? arg))."
[arg]
(if arg false true))
These are sometimes convenient when filtering values or constructing a vector of true/false values.
Later, I discovered Clojure already had a function boolean which does the same thing as truthy?.
Be sure to see this list of documentation sources, especially the Clojure CheatSheet. Enjoy!
The book Living Clojure explains that the type nil is treated
the same as logical false.
First, nil is a value - not a type.
Its type is nameless.
Any reference (object) type can have it as a value.
Second, nil and false are distinct values. You can easily write code that treats them differently:
(map #(case %, nil 1, false 2) [nil false])
=> (1 2)
And nil, for example, puns to an empty sequence,
(count nil)
=> 0
whereas false does not
(count false)
Execution error ...
It is as the first argument to if that nil is equivalent to false.
Paraphrasing the official document:
(if test then else?)
... evaluates test, then ...
if it is nil or false, evaluates and yields else;
otherwise evaluates and yields then.
If else is not supplied, it defaults to nil.
All of the other conditionals (when, if-let, cond,
...) follow the same logic:
nil and false constitute logical falsity;
everything else constitutes logical truth.
As for the predicate function false?, it might have been defined ...
(defn false? [x]
(case x, false true, false))
... which, for any argument but the exact value false, returns false.
By the way, the Clojure values false and true are the Java objects Boolean/FALSE and Boolean/TRUE:
Boolean/FALSE
=> false
(if Boolean/FALSE 1 2)
=> 2
(type false)
=> java.lang.Boolean
I've noticed in Scheme, Racket, and Clojure that the expression (using Clojure here) (and true '()) evaluates to (), and (and '() true) evaluates to true. This is true not only for the empty list, but for any list.
But in GNU CLISP and Emacs Lisp, (and t '()) evaluates to nil and (and '() t) evaluates to nil also, but (and t '(1 2 3)) evaluates to (1 2 3) and (and '(1 2 3) t) evaluates to t.
What is going on here?
In the first group of languages, the empty list is not treated as 'falsey' and is instead treated as a 'truthy' value. In scheme and racket, #false is the only false value so even though '() is null, null is not false; in clojure the empty list is not the same as nil, so it is 'truthy' there as well.
In the second group, the empty list is a synonym for nil and is treated as false, leading the condition to return nil. A list with elements however is not the same as nil, and thus is treated as a truthy value again.
The final piece of the puzzle is that and returns the last truthy value if all values passed are truthy.
In Clojure only false and nil are regarded as logically false. Everything else is regarded as logically true.
In the other Lisps you mention, the empty list is regarded as logically false.
The and operator evaluates the arguments and 'shortcircuits' the result, i.e. as soon as one argument is false, it returns nil. Otherwise, it returns the last value.
The difference in behavior is that in Common Lisp, the empty list is the same thing as nil, which is the same as false, therefore, (and '() t) is the same as (and nil t) which returns nil.
I don't get why the combination of every? and identity is giving different results in the following two examples. It seems that it gives the expected answer upon calling it on true false collections, but not with the numbers and strings:
(every? identity [1 2 3 4])=> true
(every? identity [true true false])=> false
It makes sense in your latter case that every? would return false since one of the elements in the tested collection is false; i.e.:
=> (identity false)
false
As every? works its way across the vector and encounters the above application, it sees a falsy value, so returns such.
=> (doc every?)
-------------------------
clojure.core/every?
([pred coll])
Returns true if (pred x) is logical true for every x in coll, else
false.
This is from the clojure documentation for every?:
Returns true if (pred x) is logical true for every x in coll, else
false.
By evaluating (identity) on the false value inside the array you are getting false because the identity of false is false.
According to http://hyperpolyglot.org/lisp, the only falsehoods in Clojure are false and nil. Indeed, surprisingly enough, (Boolean. false) is not false:
user=> (if (Boolean. false) 1 2)
1
user=> (not (Boolean. false))
false
user=> (false? (Boolean. false))
false
On the other hand, it somehow is false:
user=> (class false)
java.lang.Boolean
user=> (= false (Boolean. false))
true
This is rather counterintuitive. Are there reasons for this behaviour or was it simply overlooked?
You can find the explanation at http://clojure.org/special_forms#if.
It's good to read the whole paragraph, but here's the crucial bit excerpted, emphasis added:
[...] All [...] conditionals in Clojure are based upon the same logic, that is, nil and false constitute logical falsity, and everything else constitutes logical truth, and those meanings apply throughout. [...] Note that if does not test for arbitrary values of java.lang.Boolean, only the singular value false (Java's Boolean.FALSE), so if you are creating your own boxed Booleans make sure to use Boolean/valueOf and not the Boolean constructors.
Compare
System.out.println(Boolean.valueOf(false) ? true : false); // false
System.out.println(new Boolean(false) ? true : false); // false
with
user=> (if (Boolean/valueOf false) true false)
false
user=> (if (Boolean. false) true false)
true
Thus, (Boolean. false) is neither nil nor false, just as (Object.) is neither nil nor false. And as #Chiron has pointed out, it's bad practice to use it anyway.
As for (= false (Boolean. false)) being true, I think #looby's explanation is spot on: Since = relies on Java's equals method, the special semantics of conditionals in Clojure don't apply, and boolean equality will be as it is in Java.
Don't ever and never call (Boolean. true) or (Boolean. "true"). Don't create any instance of Boolean class. Those two forms are really evil.
This isn't an issue of Clojure, actually it is a Java's one.
There are only two possible values for a boolean: true or false which are already provided by Java. The constructors give you the illusion that you can create a new instance of Boolean class that can behave as a Boolean but it won't.
If you really want to create a Boolean instance from a String or a boolean, then use valueOf() method of Boolean class.
(Boolean/valueOf "true")
(Boolean/valueOf true)
Boolean.html#valueOf(boolean)
I think the reason this happens is that Clojure's = uses Java's equals method. So (= x y) is like x.equals(y). So false gets coerced into (Boolean. false) in the comparison under the hood.
Note that this does not mean that (Boolean. false) is false or that it is the 'same' as false, just that when false and (Boolean. false) are compared using the equals method they are considered to be equal.
According to http://hyperpolyglot.org/lisp, the only falsehoods in Clojure are false and nil. Indeed, surprisingly enough, (Boolean. false) is not false:
user=> (if (Boolean. false) 1 2)
1
user=> (not (Boolean. false))
false
user=> (false? (Boolean. false))
false
On the other hand, it somehow is false:
user=> (class false)
java.lang.Boolean
user=> (= false (Boolean. false))
true
This is rather counterintuitive. Are there reasons for this behaviour or was it simply overlooked?
You can find the explanation at http://clojure.org/special_forms#if.
It's good to read the whole paragraph, but here's the crucial bit excerpted, emphasis added:
[...] All [...] conditionals in Clojure are based upon the same logic, that is, nil and false constitute logical falsity, and everything else constitutes logical truth, and those meanings apply throughout. [...] Note that if does not test for arbitrary values of java.lang.Boolean, only the singular value false (Java's Boolean.FALSE), so if you are creating your own boxed Booleans make sure to use Boolean/valueOf and not the Boolean constructors.
Compare
System.out.println(Boolean.valueOf(false) ? true : false); // false
System.out.println(new Boolean(false) ? true : false); // false
with
user=> (if (Boolean/valueOf false) true false)
false
user=> (if (Boolean. false) true false)
true
Thus, (Boolean. false) is neither nil nor false, just as (Object.) is neither nil nor false. And as #Chiron has pointed out, it's bad practice to use it anyway.
As for (= false (Boolean. false)) being true, I think #looby's explanation is spot on: Since = relies on Java's equals method, the special semantics of conditionals in Clojure don't apply, and boolean equality will be as it is in Java.
Don't ever and never call (Boolean. true) or (Boolean. "true"). Don't create any instance of Boolean class. Those two forms are really evil.
This isn't an issue of Clojure, actually it is a Java's one.
There are only two possible values for a boolean: true or false which are already provided by Java. The constructors give you the illusion that you can create a new instance of Boolean class that can behave as a Boolean but it won't.
If you really want to create a Boolean instance from a String or a boolean, then use valueOf() method of Boolean class.
(Boolean/valueOf "true")
(Boolean/valueOf true)
Boolean.html#valueOf(boolean)
I think the reason this happens is that Clojure's = uses Java's equals method. So (= x y) is like x.equals(y). So false gets coerced into (Boolean. false) in the comparison under the hood.
Note that this does not mean that (Boolean. false) is false or that it is the 'same' as false, just that when false and (Boolean. false) are compared using the equals method they are considered to be equal.