2013-01-07 15 views
6

Sto cercando di convertire il seguente esempio per le nuove Clojure 1.5 riduttori libreria:Clojure riduttori biblioteca - pieghevole con max

(reduce max (map inc (range 10))) 
;=> 10 

Quando cambio it- ottengo il seguente errore:

(r/fold max (r/map inc (range 10))) 
;ArityException Wrong number of args (0) passed to: core$max clojure.lang.AFn.throwArity (AFn.java:437) 

Qualcuno può darmi una soluzione corretta?

risposta

10

Si noti che funziona quando si sostituisce max con +.

(r/fold + (r/map inc (range 10))) 
; => 55 

La differenza è il fatto che unlike +maxdoes not have un caso di una chiamata senza argomenti. r/fold richiede la funzione di combinazione-i.e. max - per fornire un valore di identità quando viene chiamato senza argomenti. Per * è 1, per + è 0.

Una possibile soluzione sarebbe quella di definire un max' che funge da max ma quando viene chiamato senza argomenti restituisce l'infinito negativo- an identity element per la funzione max.

(defn max' 
    ([] Double/NEGATIVE_INFINITY) 
    ([& args] (apply max args))) 
(r/fold max' (r/map inc (range 10))) 
; => 10 

Lo stesso risultato si può ottenere utilizzando la funzione r/monoid.

(r/fold (r/monoid max #(Double/NEGATIVE_INFINITY)) (r/map inc (range 10))) 

Per ulteriori approfondimenti si veda Reducers - A Library and Model for Collection Processing, sezione semplicità è Opportunità.

+0

Ok: sembra che l'abbiano discusso nel gruppo Google qui: https://groups.google.com/forum/?fromgroups=#!searchin/clojure/reduce$20max/clojure/EJ9hOZ8yaos/TULab4pndwoJ – hawkeye

+1

@ Jan C'è un aiuto fn chiamato 'monoid' per questo, usando quello, il tuo secondo esempio di codice si riduce ad es '(r/fold (r/monoid max # (Double/NEGATIVE_INFINITY)) (r/map inc (range 10)))' –

+0

@EugeneBeresovksy, grazie, non sapevo nulla della funzione 'monoid'. Ho aggiornato la risposta. – Jan