Reputation: 348
Why does the second operation computes to false? Does the "or" argument function differently in clojure? If so, how should I write the operation so it computes to true regardless of where the 0 is in the argument?
(= (or 0 1) 0) ; true
(= (or 1 0) 0) ; false
Upvotes: 4
Views: 326
Reputation: 22021
(or)(or x)(or x & next)
- evaluates expressions one at a time, from left to right.
If form returns 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 nil
if last expression are falsy
(Source: Clojure documentation ).
In first statement (= (or 0 1) 0)
the (or 0 1) return 0
because it's is logical true
( in clojure inly nil
and false
are falsy) then compare with 0
so result is true
.
In second statement (= (or 1 0) 0)
it returns 1
and compare it to 0
and returns false because they aren't equal.
Upvotes: 5
Reputation: 13473
You are testing logical values for equality. This is a code smell in most languages and worse in Clojure.
(or 0 1) ; 0
(or 1 0) ; 1
... since both 0
and 1
are logically true, and or
returns its first logically true argument (or the last argument, if there is no true one). The only things that aren't true are nil
and false
(and its boxed form Boolean/FALSE
).
The fact that or
is a macro is incidental in this case.
Upvotes: 2
Reputation: 81
In Clojure nil
and false
are falsy, everything else is truthy.
If you want the result of the expression to be true when there is a zero in a list, you should test if some elements of the list are equal to zero.
(some zero? [0 1])
Upvotes: 3
Reputation: 37008
or
is no function - it is a macro. it expands to if
calls and by that the rules of if
truth apply: nil
or false
are flasey, everything else is truthy - including 0
.
user=> (when 0 (println "true"))
true
nil
Your code expands to:
user=> (macroexpand '(or 1 0))
(let* [or__4238__auto__ 1] (if or__4238__auto__ or__4238__auto__ (clojure.core/or 0)))
So in short, or
's generated code returns the first truthy argument -- or the last one.
So if you want to know, if your list there contains any zero use something more appropriate:
user=> (some zero? [1 2 3])
nil
user=> (some zero? [1 2 0])
true
Or in case the 0
there is a param too:
user=> (some #{0} [1 2 3])
nil
user=> (some #{0} [1 2 0])
0
Upvotes: 3
Reputation: 1268
or returns the first non-false value or false. So in your examples or will return the first number in the argument list, zero or otherwise.
Upvotes: 3