Rich Hickey's Strange Loop transducers presentation告诉我们,Clojure 1.6中有两个map
实现,一个用于clojure.core
中的序列,另一个用于core.async
中的频道。
现在我们知道在1.7中我们有换能器,当给定a时,foldr
(reduce
)函数从高阶函数返回,如map
和filter
功能但不是集合。
我正在努力表达和失败,这就是为什么core.async
函数不能返回序列,或者Seq
- 就像。我有一种感觉,'接口'(协议)是不同的,但我看不出如何。
当然,如果您从频道中取出第一个项目,那么您可以将其表示为从序列中取出第一个项目吗?
我的问题是: core.async
能否按顺序实现其功能?
答案 0 :(得分:9)
是的,从某种意义上说,他们本来可以。如果你忽略了去块(暂时让我们这样做),那么下面的内容确实没有错:
(defn chan-seq [ch]
(when-some [v (<!! c)]
(cons v (lazy-seq (chan-seq ch)))))
但请注意<!!
电话。这称为“阻塞”:在此函数内部是一些promise和lock,它们将导致当前正在执行的线程停止,直到通道上有值。因此,如果您不介意让Java线程无所事事,那么这样可以正常工作。
go block背后的想法是使逻辑过程更便宜;为了实现这一点,go块将块的主体重写为一系列附加到通道的回调,这样在go块内部对<!
的调用就会变成这样的{{1}其中(take! c k)
是对go块其余部分的回调。
现在,如果我们有真正的延续,或者JVM支持轻量级线程,那么是的,我们可以组合go-blocks和阻塞。但目前这涉及深度字节码重写(如Pulsar / Quasar项目)或某些非标准JVM功能。这两个选项都在core.async的创建中被排除,有利于实现更简单(并且希望更容易推理)本地块转换。