2010-06-21 216 views
11

如何評估Clojure中的(不純)函數列表?例如:如何評估Clojure中不純功能的序列?

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

預期輸出是:

1 
2 
3 

有沒有辦法實現這一目標而無需使用宏?像(map evaluate fns-seq),也許?

(我需要這個使用Clojure.processing API繪製一些圖形。)

回答

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

大,即工作。非常感謝! – 2010-06-22 20:00:00

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.core中的clojure.contrib.seq-utils中找到1.2的當前快照。

更新:注意reductions返回一個懶惰的序列,因此它在map沒有改善(特別注意:在map你想使用#(%)而非#(%2))。我在這裏提到它主要是爲了完整性。事實上,我發佈了完整答案,因爲通常我會採用doseq方法(請參閱Brian的答案)。

+0

感謝您的額外評論。我可以想象,當處理來自命令性Java世界的圖書館時,我的「問題」會更頻繁地出現。也許一個宏(dofns fns)會是一個很好的抽象,這在Clojure中目前是缺少的。 – 2010-06-22 20:05:02

1

(apply pcalls [#(println "1") #(println "2") #(println "3")])就是這樣做的。請謹慎對待pcalls'並行性(因此缺乏順序性)和懶惰。

+0

很高興知道pcalls :) – nXqd 2016-03-28 09:33:18

0

我知道一個老問題,但還有另一種選擇。 你可以簡單地invoke功能:

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

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

這使您可以在不同的上下文決定你希望如何執行功能(比如,pmap,或claypoole'supmap例如)