2014-11-13 15 views
5

To jest aktualna wersja kodu, który wykonuje bardzo proste zadanie. Rozpoczyna 10 rutynowych procedur, a każda rutyna dodaje 10 komunikatów do kanału. Drugi koniec to prawdziwa pętla, która odczytuje kanał i kończy się co 500 ms.Jaki jest idiomatyczny sposób oczekiwania na kanał asynchroniczny Clojure?

Myślałem o czymś lepszym. Myślę, że prawdziwa pętla może zostać zastąpiona powtórzeniem, w którym odczytuje kanał i po każdym pomyślnym przeczytaniu wraca do ponownego przeczytania. Jeśli dojdzie do przekroczenia limitu czasu, po prostu kończy wykonywanie.

Mam dwa pytania: - czy to właściwe podejście? - jak wdrożyć go za idiomatyczne Clojure

(defn -main [& args] 
    (let [c (async/chan)] 
    (doseq [i (range 10)] 
     (async/go 
     (doseq [j (range 10)] 
      (Thread/sleep (rand-int 1000)) 
      (async/>! c (str i " :: " j))))) 
    (while true 
    (async/<!! 
     (async/go 
     (let [[result source] (async/alts! [c (async/timeout 500)])] 
      (if (= source c) 
      (println "Got a value!" result) 
      (println "Timeout!")))))))) 
+2

Nazwałbym każde użycie 'wątku/uśpienia' w core.async code ** zawsze ** zapachu kodu - wypełniasz swoją pulę wątków bez żadnego powodu. Nie można wymyślić żadnego scenariusza, w którym '

+0

... i, tak, zgadzam się, że odczyt pętli/powtórzenia z kanału byłby idiomatyczny. –

Odpowiedz

7

Jest to bardzo powszechne podejście, tak aby odpowiedzieć na pierwsze pytanie, powiedziałbym tak. Istnieje kilka udogodnienia oferowane przez core.async które mogłyby uczynić go nieco więcej idomatic (choć to naprawdę w porządku tak jest):

  • użycie go-loop w preferencji do (go (while true ...)) lub (go (loop ...))
  • użycie alt! zamiast do (let [[result channel]] (alts! ...))
Powiązane problemy