Domanda

Voglio applicare una serie di test sulla mia lista e assicurarmi che tutti i test siano stati superati. Esiste una funzione simile a " andmap " in Clojure?

È stato utile?

Soluzione

Puoi usare ogni? :

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

Ecco la documentazione su ogni? .

Altri suggerimenti

Clojure 1.3 aggiungerà every-pred (e il relativo some-fn per la versione " o ")

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

Prende un insieme di predicati e restituisce una funzione f che restituisce vero se tutti i suoi   i predicati di composizione restituiscono un valore logico vero rispetto a tutti i suoi argomenti, altrimenti restituisce   falsa. Si noti che f è in corto circuito in quanto interromperà l'esecuzione sul primo   argomento che attiva un risultato logico falso rispetto ai predicati originali.

Un'implementazione ingenua potrebbe essere:

(defn every-pred [& amp; preds] (fn [& amp; args] (every? # (every?% args) preds)))

ma l'implementazione effettiva avrà prestazioni migliori.

Ho scritto andmap come una macro che accetta i predicati come argomenti e crea una funzione che "avvolge un e attorno ai predicati", ovvero,

(andmap integer? odd?) 
==>
(fn [x] (and (integer? x)
             (odd? x)))

(non si espande in esattamente questo, ma si espande in qualcosa di equivalente a questo)

Questo ha il vantaggio di scorciatoia sui predicati in modo da poter scrivere

(every? (andmap integer? odd?) [1 3 "a string"])

senza ottenere un'eccezione di runtime come si otterrebbe con Risposta di Arthurs .

Ecco la definizione di andmap :

(defmacro andmap 
  ([]       `(fn [& x#] true))
  ([p & ps] `(fn [& x#] (and (apply ~p x#)
                             (apply (andmap ~@ps) x#)))))

È anche possibile definire andmap come una funzione che cortocircuita sui suoi predicati a causa della pigrizia:

(defn andmap [& ps]
  (fn [& x]
    (every? true? (map (fn [p] (apply p x)) ps))))

I predicati su andmap possono accettare un numero arbitrario di argomenti, quindi è possibile scrivere

(map (andmap #(and (integer? %1)
                   (integer? %2))
             #(and (odd? %1)
                   (even? %2))
             <)
     [1 3 9]
     [2 6 "string"])

che valuta (true true false) .

ogni? chiederà " Questa funzione ritorna vera per ogni membro del seq " ;, che è vicino a quello che penso tu stia chiedendo. Un miglioramento su ogni? richiederebbe un elenco di funzioni e chiederebbe " Tutti questi predicati sono veri per ogni membro di questo seq " ;.

Ecco un primo tentativo:

(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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top