如何在Clojure中评估(不纯)函数列表?例如:
[#(println "1") #(println "2") #(println "3")]
预期输出为:
1
2
3
有没有办法在不使用宏的情况下实现这一目标?像(map evaluate fns-seq)
这样的东西,可能吗?
(我需要使用Clojure.processing API绘制一些图形。)
答案 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)))
这允许您在不同的上下文中决定如何执行这些功能(例如,pmap
或claypoole's upmap
)