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