Ertuğrul Çetin
Ertuğrul Çetin

Reputation: 5231

Why some? returns true when it takes false as a parameter in Clojure?

I couldn't understand the intent of some? function in Clojure.

I need some function(built-in) that returns false when it takes (nil or false).

Here is the example:

(some? "1")
=> true

(some? nil)
=> false

(some? false) ;;Which is odd!!
=> true

Upvotes: 1

Views: 972

Answers (5)

Alan Thompson
Alan Thompson

Reputation: 29966

While there is more than one way to do what you are asking, I think the easiest is to use the truthy? & falsey? functions from the Tupelo library:

The Truth Is Not Ambiguous

Clojure marries the worlds of Java and Lisp. Unfortunately, these two worlds have different ideas of truth, so Clojure accepts both false and nil as false. Sometimes, however, you want to coerce logical values into literal true or false values, so we provide a simple way to do that:

(truthy? arg)
  Returns true if arg is logical true (neither nil nor false);
  otherwise returns false.

(falsey? arg)
  Returns true if arg is logical false (either nil or false);
  otherwise returns false. Equivalent to (not (truthy? arg)).

Since truthy? and falsey? are functions (instead of special forms or macros), we can use them as an argument to filter or any other place that a higher-order-function is required:

(def data [true :a 'my-symbol 1 "hello" \x false nil] )

(filter truthy? data)
;=> [true :a my-symbol 1 "hello" \x]
(filter falsey? data)
;=> [false nil]

(is (every? truthy? [true :a 'my-symbol 1 "hello" \x] ))
(is (every? falsey? [false nil] ))

(let [count-if (comp count keep-if) ]
  (let [num-true    (count-if truthy? data)   ; <= better than (count-if boolean data)
        num-false   (count-if falsey? data) ] ; <= better than (count-if not     data)
    (is (and  (= 6 num-true)
              (= 2 num-false) )))))

Upvotes: 1

Thumbnail
Thumbnail

Reputation: 13483

The effective source for some? is

(defn some? [x] (not (nil? x)))

It would be better called not-nil?, which Tupelo offers as an alias.

As others have said, the function you are looking for is boolean.

Upvotes: 0

Neikon
Neikon

Reputation: 169

Even simpler, use IF:

user=> (if "1" true false)
true
user=> (if nil true false)
false
user=> (if false true false)
false

Upvotes: 1

Piotrek Bzdyl
Piotrek Bzdyl

Reputation: 13185

Check the documentation of some?:

(some? x)

Returns true if x is not nil, false otherwise.

false is definitely not nil thus (some? false) returns true.

It is a complement of nil?

(= (some? x) (not (nil? x))

As @delta suggested, you can use boolean to check if something is not nil or false.

Upvotes: 5

delta
delta

Reputation: 3818

Don't know why some? is like that. But what you are looking for is boolean.


  1. https://clojuredocs.org/clojure.core/boolean

Upvotes: 4

Related Questions