Esiste una funzione simile a & # 8220; andmap & # 8221; in clojure?
-
06-07-2019 - |
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?
Soluzione
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