Existe uma função semelhante a “andmap” em Clojure?
-
06-07-2019 - |
Pergunta
Eu quero aplicar uma série de testes na minha lista e certifique-se que todos os testes são passados. Existe uma função semelhante a "andmap" em Clojure?
Solução
Você pode usar every?
:
user=> (every? string? '("hi" 1))
false
Aqui está a documentação sobre every?
.
Outras dicas
Clojure 1.3 irá adicionar todos os-pred (eo relacionado some-fn para a versão "ou").
clojure.core / cada-pred ([P] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps])
Toma um conjunto de predicados e retorna uma função f que retorna verdadeiro se todos os seus predicados que compõem retornar um valor verdadeiro lógico contra todos os seus argumentos, senão ele retorna falso. Note-se que f é um curto-circuito em que ele irá parar a execução no primeiro argumento de que desencadeia um falso resultado lógico contra os predicados originais.
Uma implementação simples pode ser:
(defn cada-pred [& Preds] (FN [& args] (todos? # (Cada?% Args) Preds)))
mas a aplicação concreta terá melhor desempenho.
Eu escrevi andmap
como uma macro que leva predicados como seus argumentos e constrói uma função que "envolve um and
em torno dos predicados", i.,
(andmap integer? odd?)
==>
(fn [x] (and (integer? x)
(odd? x)))
(não expandir para exatamente isso, mas ele se expande para algo equivalente a isso)
Isto tem a vantagem de que shortcuircuts sobre os predicados assim você pode escrever
(every? (andmap integer? odd?) [1 3 "a string"])
sem obter uma exceção de tempo de execução que você obteria com Arthurs responder .
Aqui é a definição de andmap
:
(defmacro andmap ([] `(fn [& x#] true)) ([p & ps] `(fn [& x#] (and (apply ~p x#) (apply (andmap ~@ps) x#)))))
Também é possível definir andmap
como uma função que também curto-circuitos, por si predicados devido a preguiça:
(defn andmap [& ps] (fn [& x] (every? true? (map (fn [p] (apply p x)) ps))))
Os predicados para andmap pode ter um número arbitrário de argumentos, por isso é possível escrever
(map (andmap #(and (integer? %1)
(integer? %2))
#(and (odd? %1)
(even? %2))
<)
[1 3 9]
[2 6 "string"])
que avalia a (true true false)
.
every?
vai perguntar "Será que esta função return true para cada membro da seq", que é próximo ao que eu acho que você está pedindo. Uma melhoria em every?
levaria uma lista de funções e perguntar: "Será que todos esses predicados verdadeiros para cada membro desta seq".
Aqui está uma primeira tentativa:
(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