【问题标题】:Why am I only getting one take! from this channel?为什么我只拍一张!从这个频道?
【发布时间】:2014-05-23 07:27:22
【问题描述】:

试图了解渠道的运作方式;我不明白为什么我的take! 在这个 REPL 序列中只工作一次,即使我在此过程中尝试了多次放置:

cplay.core> (def h (chan))
#'cplay.core/h
cplay.core> (go (put! h "hello"))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@4afdd6ba>
cplay.core> (go (take! h (fn [x] (println x))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@9fe39a1>
cplay.core> hello

cplay.core> (go (take! h (fn [x] (println x))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@206564e9>
cplay.core> (go (put! h "hello"))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@6c0ec468>
cplay.core> (go (take! h (fn [x] (println x))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@60c85184>
cplay.core> (go (take! h (fn [x] (println x))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@3edc08c3>
cplay.core> (go (take! h (fn [x] (println x))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@6a7b295f>
cplay.core> (go (put! h "hello"))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@60331d8b>
cplay.core> (go (take! h (fn [x] (println x))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@557c3bce>
cplay.core> (go (put! h "hello"))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@203fdcfb>
cplay.core> (go (put! h "hello"))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@ed11c1>
cplay.core> (go (take! h (fn [x] (println x))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@6c7ea146>
cplay.core> 

是不是因为当通道上没有任何东西时我连续几次从通道中取出,从而留下由后续 put 填充的“空白”,直到通道以某种方式恢复到偶数的 put 和 take?

【问题讨论】:

  • 这是你真正的输出吗?我希望第二个(fn [x] (println x) 部分运行并输出hello,一旦您在“空”通道块上调用take! 后第二次调用(go (put! h "hello")),直到消息到达。
  • @sloth 是的,这完全是从我的 REPL 复制而来的
  • 我无法使用 core.async 0.1.303.0-886421-alpha 重现此问题。你用的是哪个版本?
  • @sloth 是的,我今天使用的是最新版本

标签: clojure


【解决方案1】:

在这种异步场景中,println 的行为非常奇怪。 如果您的最后一次调用是“take!” fn 那么你最终会在你的 repl 中得到打印结果,但是最后一次调用是“put!”。 fn 那么你必须在 nrepl-server 终端上找到打印结果。

在 core.async 的Timothy Baldridge video 开头引入了这种行为和必要的工作空间

这里是 one screenshot 我在 emacs 中的 2 个帧,一个用于 nrepl,另一个用于 nrepl-server 输出

【讨论】:

  • 你不知道吗,我在 Emacs 中切换到我的 nrepl 缓冲区,它们都在那里。
  • 无论如何@edbond 正确地指出你没有必要使用 go 宏来使用 take!然后放!
【解决方案2】:

不要用go 包裹put!take!。里面去你想要&lt;!!&gt;

user=> (require '[clojure.core.async :refer (chan put! take! <! >!)])
nil
user=> (def h (chan))
#'user/h
user=> (put! h "hello")
true
user=> (take! h println)
hello
nil
user=> (put! h "hello")
true
user=> (take! h println)
hello
nil
user=> (put! h "hello")
true
user=> (take! h println)
hello
nil
user=> (put! h "hello")
true
user=> (take! h println)
hello
nil
user=> (take! h println)
nil
user=> (put! h "hello")
hello
true

【讨论】:

猜你喜欢
  • 2017-10-26
  • 2023-04-10
  • 2023-01-04
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多