2010-06-21 14 views
11

Jak mogę ocenić listę (nieczystych) funkcji w Clojure? Na przykład:Jak ocenić sekwencję nieczystych funkcji w Clojure?

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

oczekiwany wynik to:

1 
2 
3 

Czy istnieje sposób, aby to osiągnąć bez użycia makr? Coś jak (map evaluate fns-seq), może?

(muszę to na rysunku niektóre grafiki używając API Clojure.processing.)

Odpowiedz

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

Wielkiego, który pracował . Wielkie dzięki! –

5

To będzie chętnie spożywają całą nast, nazywając wszystkie funkcje efektów ubocznych i powrocie co ostatni powraca:

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

Jeśli chcesz trzymać obie wartości, można użyć reductions zamiast:

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

reductions znajduje się w clojure.contrib.seq-utils w Clojure 1.1 oraz w clojure.core w bieżących migawkach wersji 1.2.

Aktualizacja: Zauważ, że reductions zwraca leniwe nast, więc to nie jest postęp w stosunku map (. NB w map którą chcesz użyć #(%) zamiast #(%2)). Wspominałem o tym głównie dla kompletności. W rzeczywistości, napisałem całą odpowiedź dla kompletności, ponieważ zwykle podążałem za podejściem doseq (patrz odpowiedź Briana).

+0

Dziękujemy za dodatkowe komentarze. Mogę sobie wyobrazić, że mój "problem" będzie się częściej pojawiał, gdy zajmiemy się bibliotekami z imperatywnego świata Java. Może makro (dofns fns) byłoby ładną abstrakcją, której obecnie brakuje w Clojure. –

1

(apply pcalls [#(println "1") #(println "2") #(println "3")]) właśnie to robi. Po prostu bądźcie ostrożni przed paralelizmem (a więc brakiem sekwencyjności) i leniwością.

+0

Dobrze wiedzieć pcalls :) – nXqd

0

Stare pytanie, wiem, ale jest inna opcja. Można było po prostu invoke funkcje:

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

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

Pozwala zdecydować, w innym kontekście, jak chcesz realizować funkcje (powiedzmy, pmap lub claypoole'supmap na przykład)

Powiązane problemy