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?

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top