2012-08-11 17 views
5

Supponiamo di avere tre funzioni di arità 1, 2 e 3, come di seguito:È possibile che il clojure valuti una catena di funzioni miste e restituisca una funzione parziale se necessario?

(defn I [x] x) 
(defn K [x y] x) 
(defn S [x y z] (x z (y z))) 

Ha clojure hanno una funzione di valutazione o di linguaggio per la valutazione:

(I K S I I) as (I (K (S (I (I))))) 

restituire una funzione parital di arietà 2?

Sto prendendo in considerazione la creazione di una macro che può assumere le definizioni di funzione semplice di cui sopra ed espanderle a funzioni multi-area che possono restituire risultati parziali. Non vorrei creare la macro se esiste già un modo integrato o idiomatico per ottenere ciò.

Ecco ciò che le macro espanse vorrebbero per le funzioni di cui sopra:

(defn I 
    ([x] I x) 
    ([x & more] (apply (I x) more))) 

(defn K 
    ([x] (partial K x)) 
    ([x y] x) 
    ([x y & more] (apply (K x y) more))) 

(defn S 
    ([x] (partial S x)) 
    ([x y] (partial S x y)) 
    ([x y z] (x z (y z))) 
    ([x y z & more] (apply (S x y z) more))) 
+0

Ho appena trovato questo e ho pensato che * potrebbe * essere perfetto per te, e se non altro, almeno utile ... http: //alfredodinapoli.wordpress.com/2011/03/16/a-bit-of -clojure-magic-and-high-order-functions-are-served/ –

risposta

5

io non sono sicuro di comprendere appieno ciò che si sta cercando di fare, ma la funzione comp è utile per fare questo tipo di "funzione di concatenamento" di cui sembra parlare. Per esempio:

user> ((comp vec rest list) 1 2 3 4 5) 
=> [2 3 4 5] 

che è equivalente a:

user> (vec (rest (list 1 2 3 4 5))) 
=> [2 3 4 5] 

Nel tuo caso, se avete la lista (I K S I I), e si desidera valutare come (I (K (S (I (I))))), userei (reduce comp ...), ma si potrebbe utilizzare anche (apply comp ...).

user> ((reduce comp [vec rest list]) 1 2 3 4 5) 
=> [2 3 4 5] 
user> ((apply comp [vec rest list]) 1 2 3 4 5) 
=> [2 3 4 5] 

Potresti essere interessato ai -> o ->> macro. Queste macro annidano i loro argomenti in sequenza negli argomenti successivi. La macro -> verrà annidata nella prima posizione dell'espressione successiva, mentre la macro ->> verrà annidata nell'ultima posizione dell'espressione successiva. Se "next thing" è una funzione, entrambi si comportano allo stesso modo e formano un'espressione di (function nested-things-so-far) e continuano.

Davvero, esempi sono i migliori:

(-> 1 (+ 10) (- 100) inc) 
;//Expands to... 
(inc (- (+ 1 10) 100)) 
;//Evaluating in the REPL... 
user> (-> 1 (+ 10) (- 100) inc) 
=> -88 

(->> 1 (+ 10) (- 100) inc) 
;//Expands to... 
(inc (- 100 (+ 10 1))) 
;//Evaluating in the REPL... 
user> (-> 1 (+ 10) (- 100) inc) 
=> 90 

Tuttavia, sembra più come si vuole fare qualcosa che coinvolge auto-currying (anche se, ancora una volta, non credo Capisco perfettamente), e per questo Non conosco nulla di pre-esistente come built-in.

+0

Grazie per questa risposta. Mi ci vorrà un po 'di tempo per capire se può semplificare quello che sto facendo da quando sono nuovo alla programmazione di tipo clojure e lisp. A volte so cosa voglio fare ma non ho idea di come si chiama e anche quando ho un buon termine di ricerca, i risultati per il clojure sono molto limitati. Solo scoprire che quello che sto cercando di fare potrebbe essere chiamato "auto-curring" è di grande aiuto. – dansalmo