Есть ли функция, похожая на "andmap" в clojure? - PullRequest
5 голосов
/ 31 июля 2009

Я хочу применить серию тестов в своем списке и убедиться, что все тесты пройдены. Есть ли в Clojure функция, аналогичная «andmap»?

Ответы [ 4 ]

9 голосов
/ 31 июля 2009

Вы можете использовать every?:

user=> (every? string? '("hi" 1))
false

Вот документация по every?.

2 голосов
/ 04 апреля 2011

Clojure 1.3 добавит Every-pred (и связанный с ним -fn для версии "или").

clojure.core / every-pred ([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps])

Принимает набор предикатов и возвращает функцию f, которая возвращает значение true, если все его составные предикаты возвращают логическое значение true для всех своих аргументов, в противном случае возвращает значение false.Обратите внимание, что f является коротким замыканием в том смысле, что оно остановит выполнение первого аргумента, который запускает логический ложный результат для исходных предикатов.

Наивной реализацией может быть:

(определеноpred [& preds] (fn [& args] (каждые? # (каждые?% args) preds)))

, но фактическая реализация будет иметь лучшую производительность.

1 голос
/ 31 июля 2009

Я написал 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).

1 голос
/ 31 июля 2009

every? спросит «Возвращает ли эта одна функция true для каждого члена seq», что близко к тому, о чем я думаю, вы просите. Улучшение every? позволило бы получить список функций и задать вопрос: «Являются ли все эти предикаты истинными для каждого члена этого seq».

Вот первая попытка:

(defn andmap? [data tests]
  (every? true? (for [d data, f tests]
                  (f d))))

user> (andmap? '(2 4 8) [even? pos?])
true
user> (andmap? '(2 4 8) [even? odd?])
false
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...