2012-08-11 23 views
5

Suponga que tiene tres funciones de aridad 1, 2 y 3 de la siguiente manera:¿Puede clojure evaluar una cadena de funciones mixtas y devolver una función parcial si es necesario?

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

¿Tiene clojure tiene una función de evaluación o idioma para evaluar:

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

el retorno de una función parital de aridad 2?

Estoy considerando crear una macro que pueda tomar las definiciones de funciones simples anteriores y expandirlas a funciones multiareas que pueden devolver resultados parciales. No me gustaría crear la macro si ya existe una forma incorporada o idiomática para lograr esto.

Esto es lo que las macros expandidas gustaría que las funciones anteriores:

(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

Acabo de encontrar esto, y pensé que * puede * ser perfecto para usted, y en todo caso, al menos útil ... http: //alfredodinapoli.wordpress.com/2011/03/16/a-bit-of -clojure-magic-and-high-order-functions-are-served/ –

Respuesta

5

No estoy seguro de entender completamente lo que está tratando de hacer, pero la función comp es útil para hacer este tipo de "función de encadenamiento" de la que parece estar hablando. Por ejemplo:

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

que es equivalente a:

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

En su caso, si usted tiene la lista (I K S I I), y desea evaluarlo como (I (K (S (I (I))))), me gustaría utilizar (reduce comp ...), pero se puede también use (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] 

También puede estar interesado en los -> o ->> macros. Estas macros anidan sus argumentos secuencialmente en los siguientes argumentos. La macro -> anidará en la primera posición de la siguiente expresión, mientras que la macro ->> anidará en la última posición de la siguiente expresión. Si el "siguiente elemento" es una función, ambos se comportarán igual y formarán una expresión de (function nested-things-so-far), y continuarán a lo largo.

Realmente, los ejemplos son mejores:

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

Sin embargo, parece más bien que quiere hacer algo relacionado con la auto-currificación (aunque, de nuevo, no creo que entiendo totalmente), y por esa No sé nada de manera preexistente incorporada.

+0

Gracias por esta respuesta también. Me llevará un tiempo asimilar y ver si puede simplificar lo que estoy haciendo, dado que soy nuevo en la programación de tipo clogure y lisp. A veces sé lo que quiero hacer pero no tengo ni idea de cómo se llama y, aunque tenga un buen término de búsqueda, los resultados de clojure son muy limitados. Descubrir que lo que estoy tratando de hacer podría llamarse "auto-currying" es de gran ayuda. – dansalmo

Cuestiones relacionadas