为什么Clojure的异步库不能处理Go prime筛子?

时间:2016-02-20 22:56:30

标签: asynchronous go clojure primes

为了在Clojure中试用异步库,我翻译了来自Go的主要筛选示例。在REPL中运行,它成功打印出素数高达227,然后停止。我按下Ctrl-C并尝试再次运行它,但它不会打印出更多数字。有没有办法让Clojure处理这个问题,或者异步库还没准备好呢?

;; A concurrent prime sieve translated from
;; https://golang.org/doc/play/sieve.go

(require '[clojure.core.async :as async :refer [<!! >!! chan go]])

(defn generate
  [ch]
  "Sends the sequence 2, 3, 4, ... to channel 'ch'."
  (doseq [i (drop 2 (range))]
    (>!! ch i)))

(defn filter-multiples
  [in-chan out-chan prime]
  "Copies the values from 'in-chan' to 'out-chan', removing
  multiples of 'prime'."
  (while true
    ;; Receive value from 'in-chan'.
    (let [i (<!! in-chan)]
      (if (not= 0 (mod i prime))
        ;; Send 'i' to 'out-chan'.
        (>!! out-chan i)))))

(defn main
  []
  "The prime sieve: Daisy-chain filter-multiples processes."
  (let [ch (chan)]
    (go (generate ch))
    (loop [ch ch]
      (let [prime (<!! ch)]
        (println prime)
        (let [ch1 (chan)]
          (go (filter-multiples ch ch1 prime))
          (recur ch1))))))

1 个答案:

答案 0 :(得分:2)

go是一个宏。如果你想在go块中利用类似goroutine的行为,你必须使用<!>!,它们必须对go宏可见(你不能提取)这些操作分为不同的功能)。

这个https://golang.org/doc/play/sieve.go程序的字面翻译似乎运行正常,主循环中的i更大:

(require '[clojure.core.async :refer [<! <!! >! chan go]])

(defn go-generate [ch]
  (go (doseq [i (iterate inc 2)]
        (>! ch i))))

(defn go-filter [in out prime]
  (go (while true
        (let [i (<! in)]
          (if-not (zero? (rem i prime))
            (>! out i))))))

(defn main []
  (let [ch (chan)]
    (go-generate ch)
    (loop [i 10 ch ch]
      (if (pos? i)
        (let [prime (<!! ch)]
          (println prime)
          (let [ch1 (chan)]
            (go-filter ch ch1 prime)
            (recur (dec i) ch1)))))))