【问题标题】:Why can't Clojure's async library handle the Go prime sieve?为什么 Clojure 的异步库不能处理 Go 素筛?
【发布时间】:2016-02-21 18:21:09
【问题描述】:

为了试用 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))))))

【问题讨论】:

  • 我只是查看了我自己的 core.async 代码,它有很多 &lt;!&gt;! 但没有 &lt;&lt;!&gt;&gt;!。我认为最好在 go 块内部而不是在它们外部在通道之间发送和接收。
  • go 是一个宏。如果你想在go 块中利用类似goroutine 的行为,你必须使用&lt;!&gt;!,并且它们必须对go 宏可见(即你不能将这些操作提取到单独的函数)。
  • 这行得通,谢谢!你们中的一个人可以将您的回复作为答案发布,以便我可以将其标记为解决方案吗?这是新版本:gist.github.com/ijt/577fb9e11aaf8bf14e75
  • core.async 调度程序在42+2*CPU_CORES 线程上运行。小于或等于 227 的素数正好是 49。(我猜你有 4 个 CPU 内核?)。这显示了你如何干掉所有 core.async 线程。
  • 嗨 Andre,是的,我的笔记本电脑有 4 个内核。

标签: asynchronous go clojure primes


【解决方案1】:

go 是一个宏。如果你想在 go 块中利用类似 goroutine 的行为,你必须使用 &lt;!&gt;!,并且它们必须对 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)))))))

【讨论】:

  • 这可能会作为一个 core.async 示例很好。
猜你喜欢
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 2021-11-12
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多