为什么Clojure的异步库不能处理Go的素数筛法?

huangapple go评论82阅读模式
英文:

Why can't Clojure's async library handle the Go prime sieve?

问题

尝试在Clojure中使用异步库时,我将Go语言中的素数筛选示例进行了翻译。在REPL中运行时,它成功地打印出了小于227的素数,然后停止了。我按下了Ctrl-C并尝试再次运行它,但它不再打印出任何数字。有没有办法让Clojure处理这个问题,或者说异步库还没有准备好处理这个问题?

以下是翻译好的代码:

;; 从Go语言翻译的并发素数筛选算法
(require '[clojure.core.async :as async :refer [<!! >!! chan go]])

(defn generate
  [ch]
  "将序列2, 3, 4, ... 发送到通道 'ch'。"
  (doseq [i (drop 2 (range))]
    (>!! ch i)))

(defn filter-multiples
  [in-chan out-chan prime]
  "从 'in-chan' 复制值到 'out-chan',并删除 'prime' 的倍数。"
  (while true
    ;; 从 'in-chan' 接收值。
    (let [i (<!! in-chan)]
      (if (not= 0 (mod i prime))
        ;; 将 'i' 发送到 'out-chan'。
        (>!! out-chan i)))))

(defn main
  []
  "素数筛选算法:通过连接 filter-multiples 进程来实现。"
  (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))))))

希望对你有帮助!

英文:

To try out the async library in Clojure, I translated the prime sieve example from Go. Running in the REPL, it successfully printed out the prime numbers up to 227 and then stopped. I hit Ctrl-C and tried running it again but it wouldn't print out any more numbers. Is there a way to get Clojure to handle this, or is the async library just not ready for it yet?

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

(require &#39;[clojure.core.async :as async :refer [&lt;!! &gt;!! chan go]])

(defn generate
  [ch]
  &quot;Sends the sequence 2, 3, 4, ... to channel &#39;ch&#39;.&quot;
  (doseq [i (drop 2 (range))]
    (&gt;!! ch i)))

(defn filter-multiples
  [in-chan out-chan prime]
  &quot;Copies the values from &#39;in-chan&#39; to &#39;out-chan&#39;, removing
  multiples of &#39;prime&#39;.&quot;
  (while true
    ;; Receive value from &#39;in-chan&#39;.
    (let [i (&lt;!! in-chan)]
      (if (not= 0 (mod i prime))
        ;; Send &#39;i&#39; to &#39;out-chan&#39;.
        (&gt;!! out-chan i)))))

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

答案1

得分: 2

go是一个宏。如果你想在go块中利用类似goroutine的行为,你必须使用&lt;!&gt;!,并且它们必须对go宏可见(也就是说,你不能将这些操作提取到单独的函数中)。

这个程序的字面翻译似乎很好地工作,即使在主循环中使用了更大的i

(require '[clojure.core.async :refer [&lt;! &lt;!! &gt;! chan go]])

(defn go-generate [ch]
  (go (doseq [i (iterate inc 2)]
        (&gt;! ch i))))

(defn go-filter [in out prime]
  (go (while true
        (let [i (&lt;! in)]
          (if-not (zero? (rem i prime))
            (&gt;! out i))))))

(defn main []
  (let [ch (chan)]
    (go-generate ch)
    (loop [i 10 ch ch]
      (if (pos? i)
        (let [prime (&lt;!! ch)]
          (println prime)
          (let [ch1 (chan)]
            (go-filter ch ch1 prime)
            (recur (dec i) ch1)))))))
英文:

go is a macro. If you want to take advantage of goroutine-like behaviour in go blocks you must use &lt;! and &gt;!, and they must be visible to the go macro (that is you mustn't extract these operations into separate functions).

This literal translation of the program at https://golang.org/doc/play/sieve.go seems to work fine, also with a larger i in the main loop:

(require &#39;[clojure.core.async :refer [&lt;! &lt;!! &gt;! chan go]])

(defn go-generate [ch]
  (go (doseq [i (iterate inc 2)]
        (&gt;! ch i))))

(defn go-filter [in out prime]
  (go (while true
        (let [i (&lt;! in)]
          (if-not (zero? (rem i prime))
            (&gt;! out i))))))

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

huangapple
  • 本文由 发表于 2016年2月21日 06:56:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/35530133.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定