Я написал andmap
как макрос, который принимает предикаты в качестве аргументов и создает функцию, которая "оборачивает and
вокруг предикатов", т.е.
(andmap integer? odd?)
==>
(fn [x] (and (integer? x)
(odd? x)))
(это не расширяется до точно это, но расширяется до чего-то эквивалентного этому)
Это имеет то преимущество, что он сокращает предикаты, чтобы вы могли написать
(every? (andmap integer? odd?) [1 3 "a string"])
без получения исключения времени выполнения, как если бы вы получили Arthurs answer .
Вот определение andmap
:
(defmacro andmap
([] `(fn [& x#] true))
([p & ps] `(fn [& x#] (and (apply ~p x#)
(apply (andmap ~@ps) x#)))))
Также можно определить andmap
как функцию, которая также замыкает его предикаты из-за лени:
(defn andmap [& ps]
(fn [& x]
(every? true? (map (fn [p] (apply p x)) ps))))
Предикаты andmap могут принимать произвольное количество аргументов, поэтому можно написать
(map (andmap #(and (integer? %1)
(integer? %2))
#(and (odd? %1)
(even? %2))
<)
[1 3 9]
[2 6 "string"])
, что соответствует (true true false)
.