Clojure equivalent to Python's "any" and "all" functions?

Question:

Are there built in functions in Clojure similar to Python’s any and all functions?

For example, in Python, it’s all([True, 1, 'non-empty string']) == True.

Asked By: TorelTwiddler

||

Answers:

(every? f data) [docs] is the same as all(f(x) for x in data).

(some f data) [docs] is like any(f(x) for x in data) except that it returns the value of f(x) (which must be truthy), instead of just true.

If you want the exact same behaviour as in Python, you can use the identity function, which will just return its argument (equivalent to (fn [x] x)).

user=> (every? identity [1, true, "non-empty string"])
true
user=> (some identity [1, true "non-empty string"])
1
user=> (some true? [1, true "non-empty string"])
true
Answered By: Jeremy

In clojure and and or are quite similar to python’s all and any, with the caveat that (just like clojure.core/some) they return the element that will satifsy it… thus you can use it together with boolean to convert it

(boolean (or "" nil false)) ; "" is truthy in clojure
; => true
(boolean (and [] "" {} () 0)) ; also [], {}, () and 0 are truthy
; => true

I use boolean instead of true? since the latter will return true iff the argument is the value true… so boolean is more akin to python’s bool in that it evaluates the truthyness

Unlike some & every?, and & or are macros, so if you always want to convert the result to a boolean, you cannot simply do (def any (comp boolean or)) but you have to define a macro like

(defmacro any [& v] `(boolean (or ~@v)))
(defmacro all [& v] `(boolean (and ~@v)))

a side-effect/advantage of being macros, is that they are lazy/can shortcircuit (just like python’s and & or, that are infix binary operators however)

(any "" (/ 1 0))
; => true
(all nil (/ 1 0))
; => false

and they’re just like python’s any and all, even when called without arguments

(any)
; => false
(all)
; => true

in python:

>>> any([])
False    
>>> all([])
True

If you prefer to have to call any/all with a single list/sequence argument, you can simply do:

(defmacro all [v] `(boolean (and ~@v)))

(all [])
; => true
(all [nil (/ 1 0)])    
; => false
Answered By: berdario
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.