Подтвердить что ты не робот

Clojure эквивалент Python "любые" и "все" функции?

Существуют ли встроенные функции в Clojure, аналогичные функциям Python any и all?

Например, в Python он all([True, 1, 'non-empty string']) == True.

4b9b3361

Ответ 1

(every? f data) [docs] совпадает с all(f(x) for x in data).

(some f data) [docs] похож на any(f(x) for x in data), за исключением того, что он возвращает значение f(x) (который должен быть правдивым), а не просто true.

Если вы хотите точно такое же поведение, как в Python, вы можете использовать функцию identity, которая просто вернет свой аргумент (эквивалентно (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

Ответ 2

В clojure and и or они очень похожи на python all и any, с оговоркой, что (как и clojure.core/some) они возвращают элемент, который будет сатифровать его... таким образом вы можете использовать его вместе с boolean для его преобразования

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

Я использую boolean вместо true?, поскольку последний вернет true, если аргументом является значение true... так что boolean более сродни python bool тем, что он оценивает правду

В отличие от some и every?, and и or являются макросами, поэтому, если вы всегда хотите преобразовать результат в логическое, вы не можете просто сделать (def any (comp boolean or)), но вы должны определить макрос как

(defmacro any [& v] `(boolean (or [email protected])))
(defmacro all [& v] `(boolean (and [email protected])))

побочным эффектом/преимуществом макросов является то, что они являются ленивыми/могут замыкаться (как и python and и or, которые являются инфиксными двоичными операторами)

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

и они похожи на python any и all, даже если вызываются без аргументов

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

в python:

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

Если вы предпочитаете вызывать any/all с помощью одного аргумента списка/последовательности, вы можете просто сделать:

(defmacro all [v] `(boolean (and [email protected])))

(all [])
; => true
(all [nil (/ 1 0)])    
; => false