2014-10-30 109 views
8

Rich Hickey's Strange Loop transducers presentation告诉我们在Clojure 1.6中有两个实现map,一个用于clojure.core中的序列,另一个用于core.async中的通道。core.async是否可以通过序列实现它的功能?

enter image description here

现在我们知道,在1.7,我们有传感器,为此,foldrreduce)功能从高阶函数给出的函数,但不是一个集合返回时像mapfilter

我想表达和失败的是,为什么core.async函数不能返回序列,或者是类似于Seq。我有一种感觉,'界面'(协议)是不同的,但我不明白。

当然,如果您将第一个项目从频道中取出,那么您可以将第一个项目表示为序列?

我的问题是:难道core.async已经在序列方面实现了它的功能吗?

回答

7

是的,从某种意义上说,他们本来可以。如果你忽略了去块(此刻,让我们这样做),那么就真的没有错,像下面这样:

(defn chan-seq [ch] 
    (when-some [v (<!! c)] 
    (cons v (lazy-seq (chan-seq ch))))) 

但这里需要注意的<!!电话。这被称为“take blocking”:在这个函数内部有一些promise和锁,它们会导致当前正在执行的线程暂停,直到通道上有值。所以如果你不介意让Java线程坐在那里无所事事,那么这将工作得很好。

go blocks背后的想法是让逻辑进程更便宜;为了实现这一点,go块将块的主体重写为连接到该频道的一系列回调,以便在内部对go块内的<!的调用变成类似这样的(take! c k),其中k是回调到休息区的其余部分。

现在,如果我们有真正的延续,或者如果JVM支持轻量级线程,那么是的,我们可以结合go-blocks和阻塞需求。但是,目前这涉及深度字节码重写(如Pulsar/Quasar项目)或一些非标准的JVM特性。在创建core.async时,这两个选项都被排除在外,而更容易实现(并且希望更简单地推理)本地块转换。

相关问题