In Clojure we can use several functions to see if at least one or all elements in a collection return true
or false
for a predicate. The function every?
only returns true
if the predicate function returns true
for all elements in the collection. To function not-every?
return true
if a predicate function return false
for all elements in a collection. The some
function is a bit different (notice there is no ?
) and returns the first logical true
value from the predicate function for the elements in the collection. So the return type of the predicate doesn't have to be a Boolean
value and then the return type of some
is also not a Boolean
. If the predicate returns a Boolean
value we can use some
like a any
function (any
is not part of Clojure). Clojure provides a not-any?
function that returns true
if the predicate function returns false
for one element in the collection and false
otherwise.
The following example uses the different functions on a vector with some cartoon names:
(ns mrhaki.seq.pred (:require [clojure.test :refer [is]] [clojure.string :as str])) ;; Vector of toons to check predicates on. (def toons ["Daffy Duck" "Bugs Bunny" "Elmer Fudd" "Yosemite Sam"]) ;; Helper function to count number of names. (defn count-names [name] (count (str/split name #" "))) ;; Every toon has two names. (is (true? (every? #(= 2 (count-names %)) toons))) ;; Not every toon name starts with "A". (is (true? (not-every? #(str/starts-with? "A" %) toons))) ;; Helper function to check if the first letter ;; of both names is the same. (defn same-first-letters? [name] (let [names (str/split name #" ") first-letter (first (first names)) second-letter (first (second names))] (= first-letter second-letter))) ;; Some toons have the same first letter ;; for their first and last name. (is (true? (some same-first-letters? toons))) ;; Using set as function to check toon is in the toons vector. ;; Notice some function return the first value from the predicate function ;; that is not nil or false, instead of a boolean like with ;; every?, not-every? and not-any?. (is (not (true? (some #{"Yosemite Sam", "Road Runner"} toons)))) (is (= "Yosemite Sam" (some #{"Yosemite Sam", "Road Runner"} toons))) ;; As seen on https://clojuredocs.org/clojure.core/any_q a ;; possible implementation for any that returns true or false. (defn any [pred coll] ((comp boolean some) pred coll)) (is (true? (any #{"Yosemite Sam", "Road Runner"} toons))) ;; There is a toon name where their name length is 10. (is (false? (not-any? #(= (count %) 10) toons)))
Written with Clojure 1.10.1.