2010-06-21 38 views
11

¿Cómo puedo evaluar una lista de funciones (impuras) en Clojure? Por ejemplo:¿Cómo evaluar una secuencia de funciones impuras en Clojure?

[#(println "1") #(println "2") #(println "3")] 

El resultado esperado es:

1 
2 
3 

¿Hay una manera de lograr esto sin el uso de macros? Algo como (map evaluate fns-seq), tal vez?

(Necesito esto para dibujar algunos gráficos utilizando la API Clojure.processing.)

Respuesta

17
user> (let [fs [#(println "1") #(println "2") #(println "3")]] 
     (doseq [f fs] (f))) 
1 
2 
3 
nil 
+0

Grande, que trabajó . ¡Muchas gracias! –

5

Este entusiasmo se consuma todo el SEC, llamando a todas las funciones de efectos secundarios y devolver cualquiera que sea el último regresa:

(reduce #(%2) nil [#(println :foo) #(println :bar)]) 
; => prints :foo, then :bar, then returns nil 

Si desea aferrarse a los valores de retorno, se puede utilizar en lugar reductions:

(reductions #(%2) nil [#(println :foo) #(println :bar)]) 
; => prints :foo, then :bar, then returns (nil nil) 

reductions se encuentra en clojure.contrib.seq-utils en Clojure 1.1 y en clojure.core en las instantáneas actuales de 1.2.

Actualización: Tenga en cuenta que devuelve un reductions siguientes perezoso, por lo que no mejora con respecto a map (. NB en map que te gustaría utilizar en lugar de #(%)#(%2)). Lo mencioné aquí principalmente por completitud. De hecho, publiqué la respuesta completa para completarla, porque normalmente elegiría doseq (ver la respuesta de Brian).

+0

Gracias por sus comentarios adicionales. Puedo imaginar que mi "problema" se propagará más a menudo, cuando se trata de bibliotecas del imperativo mundo de Java. Tal vez una macro (dofns fns) sería una buena abstracción, que actualmente falta en Clojure. –

1

(apply pcalls [#(println "1") #(println "2") #(println "3")]) hace exactamente eso. Solo tenga cuidado con el paralelismo pcalls (por lo tanto, falta de secuencia) y la pereza.

+0

Es bueno saber pcalls :) – nXqd

0

Una vieja pregunta, lo sé, pero hay otra opción. simplemente podría invoke las funciones:

(defn generate-fns [] 
    [#(println "1") #(println "2") #(println "3")]) 

(dorun (pmap (memfn invoke) (generate-fns))) 

Esto le permite decidir en un contexto diferente la forma en que desea ejecutar las funciones (por ejemplo, pmap o claypoole'supmap por ejemplo)

Cuestiones relacionadas