Как оценить последовательность нечистых функций в Clojure?

Как я могу оценить список (нечистых) функций в Clojure? Например:

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

Ожидаемый результат:

1
2
3

Есть ли способ достичь этого без использования макросов? Что-то вроде (map evaluate fns-seq), может быть?

(Мне нужно это для рисования некоторых графических изображений с помощью API Clojure.processing.)

Ответ 1

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

Ответ 2

Это будет потреблять весь 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.contrib.seq-utils в Clojure 1.1 и в clojure.core в текущих моментальных снимках 1.2.

Обновление: обратите внимание, что reductions возвращает ленивый seq, поэтому он не улучшается по сравнению с map (NB. в map, который вы хотите использовать #(%), а не #(%2)). Я упомянул об этом здесь в основном для полноты. Фактически, я опубликовал весь ответ для полноты, потому что обычно я бы пошел с подходом doseq (см. Ответ Брайана).

Ответ 3

(apply pcalls [#(println "1") #(println "2") #(println "3")]) делает именно это. Просто опасайтесь pcalls 'parallelism (следовательно, отсутствие последовательности) и ленивости.

Ответ 4

Старый вопрос, я знаю, но есть другой вариант. Вы могли бы просто invoke выполнять следующие функции:

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

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

Это позволяет вам решить в другом контексте, как вы хотите выполнять функции (например, pmap, или claypoole upmap например)