2012-08-11 9 views
5

Angenommen, Sie drei Funktionen von arity 1, 2 und 3, wie unten haben:Kann clojure eine Kette von gemischten Funktionen auswerten und bei Bedarf eine Teilfunktion zurückgeben?

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

Hat clojure hat eine Bewertungsfunktion oder Idiom für die Bewertung:

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

2 eine parital Funktion von arity Rückkehr?

Ich überlege mir, ein Makro zu erstellen, das die obigen einfachen Funktionsdefinitionen übernehmen und zu Multiaritätsfunktionen erweitern kann, die Teilergebnisse liefern können. Ich würde das Makro nicht erstellen wollen, wenn es bereits einen eingebauten oder idiomatischen Weg dafür gibt. Hier

ist, was die erweiterten Makros für die oben genannten Funktionen möchten:

(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

Gerade gefunden, und dachte, es * könnte * perfekt für Sie sein, und wenn nichts anderes, zumindest hilfreich ... http: //alfredodinapoli.wordpress.com/2011/03/16/a-bit-of -clojure-magic-and-high-order-functions-served/ –

Antwort

5

Ich bin nicht sicher, ich voll und ganz verstehen, was Sie zu tun versuchen, aber die comp Funktion ist hilfreich bei dieser Art von "Funktionskette", von der Sie zu sprechen scheinen. Zum Beispiel:

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

das entspricht:

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

In Ihrem Fall, wenn Sie die Liste (I K S I I) haben, und Sie wollen es als (I (K (S (I (I))))) zu bewerten, würde ich (reduce comp ...) verwenden, aber man konnte Verwenden Sie auch (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] 

Sie können auch in den -> oder ->> Makros interessiert. Diese Makros verschachteln ihre Argumente sequenziell in die nächsten Argumente. Das Makro -> wird an der ersten Position des nächsten Ausdrucks verschachtelt, während das Makro ->> an der letzten Position des nächsten Ausdrucks verschachtelt wird. Wenn das "nächste Ding" eine Funktion ist, verhalten sich beide gleich und bilden einen Ausdruck von (function nested-things-so-far) und fahren fort.

Wirklich, Beispiele sind am besten:

(-> 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 

aber es scheint, wie Sie etwas beteiligt Auto-currying tun wollen (obwohl, wieder, ich glaube nicht, dass ich voll und ganz verstehen), und für die Ich weiß nichts von einem bereits vorhandenen eingebauten Weg.

+0

Vielen Dank auch für diese Antwort. Ich werde eine Weile brauchen, um zu grunzen und zu sehen, ob es das vereinfachen kann, was ich mache, seit ich neu bin, um Programmieren und Lispeln zu lernen. Manchmal weiß ich, was ich tun möchte, habe aber keine Ahnung, wie es heißt, und selbst wenn ich einen guten Suchbegriff habe, sind die Ergebnisse für clojure sehr begrenzt. Es ist eine große Hilfe, herauszufinden, dass das, was ich versuche, als "Autocurry" bezeichnet wird. – dansalmo