如何评估Clojure中的一系列不纯函数?

时间:2010-06-21 22:04:20

标签: clojure

如何在Clojure中评估(不纯)函数列表?例如:

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

预期输出为:

1
2
3

有没有办法在不使用宏的情况下实现这一目标?像(map evaluate fns-seq)这样的东西,可能吗?

(我需要使用Clojure.processing API绘制一些图形。)

4 个答案:

答案 0 :(得分:17)

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

答案 1 :(得分:5)

这将急切地消耗整个seq,调用副作用的所有函数并返回最后一个返回的内容:

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

如果您想保留返回值,可以改为使用reductions

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

reductions位于Clojure 1.1中的clojure.contrib.seq-utils和位于1.2的当前快照中的clojure.core中。

更新:请注意,reductions会返回一个懒惰的seq,因此与map相比没有任何改进(map中您想要使用的{NB。} { {1}}而不是#(%))。我在这里提到它主要是为了完整性。事实上,我发布了完整性的答案,因为通常我会采用#(%2)方法(参见Brian的回答)。

答案 2 :(得分:1)

(apply pcalls [#(println "1") #(println "2") #(println "3")])就是这么做的。只要警惕pcalls'并行性(因此缺乏序列性)和懒惰。

答案 3 :(得分:0)

我知道一个老问题,但还有其他选择。 你可以简单地invoke函数:

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

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

这允许您在不同的上下文中决定如何执行这些功能(例如,pmapclaypoole's upmap