Clojure Clojure.core.reducers/fold和Scala fold之间有什么区别?
我发现Clojure有Clojure Clojure.core.reducers/fold和Scala fold之间有什么区别?,scala,clojure,Scala,Clojure,我发现Clojure有Clojure.core.reducers/fold函数 Scala还有内置的fold功能,但无法理解它们的工作方式是否不同?clojure.core.reducers名称空间是为并行处理大型数据集而设计的专用实现。您可以在此处找到完整的文档: r/fold获取一个可约集合,并将其划分为若干组 大约n个(默认512个)元素。每个组使用 reducef函数。将调用reducef函数,但不使用 用于在每个分区中生成标识值的参数。结果 然后使用combinef(默认为 redu
Clojure.core.reducers/fold
函数
Scala还有内置的
fold
功能,但无法理解它们的工作方式是否不同?clojure.core.reducers名称空间是为并行处理大型数据集而设计的专用实现。您可以在此处找到完整的文档:
r/fold获取一个可约集合,并将其划分为若干组
大约n个(默认512个)元素。每个组使用
reducef函数。将调用reducef函数,但不使用
用于在每个分区中生成标识值的参数。结果
然后使用combinef(默认为
reducef)函数。在没有参数的情况下调用时,(combinef)必须
生成其标识元素-此元素将被多次调用。
操作可以并行执行。结果将维持秩序
在将机器最大化之前,您应该坚持使用基本的
reduce
功能:
(reduce + 0 [1 2 3 4 5]) => 15
这与Scala的折叠功能基本相同:
(reduce + 0 [1 2 3 4 5]) => 15
其中,函数签名为:
(reduce <op> <init-val> <collection-to-be-reduced> )
(减少)
我想你说的是
Scala在序列上的默认实现非常简单:
collection.fold(identityElem)(binOp)
只需从identitylem
开始,然后依次遍历集合,并将二进制操作binOp
应用于已累积的结果和当前序列值,例如
(1 to 3).fold(42000)(_ + _)
将导致42000+1+2+3
=42006
Clojure的折叠
带有完整签名
(r/fold n combinef reducef coll)
从以上提到的包工程并行分为两个阶段。首先,它将输入分成大小为n
(大约)的较小组,然后使用reducef
减少每组,最后使用combinef
合并每组的结果
主要区别在于combinef
应同时是零元和二进制(Clojure具有多元函数),并且将调用(combinef)
(无参数)为每个分区生成标识元素(因此,是正确的,并且是谎言)
也就是说,为了从上面的示例中模拟Scala的折叠,必须编写如下内容:
(require '[clojure.core.reducers :as r])
(r/fold 3 (fn ([] 42000) ([x y] y)) + [1 2 3])
一般来说,Scala的折叠
collection.fold(identityElement)(binOp)
可通过减速器/折叠器进行模拟,如下所示:
(r/fold collectionSize (fn ([] identityElem) ([x y] y)) binOp collection)
(请注意,([xy]y)
装置丢弃了第一个参数,这是故意的)
我猜该接口不打算与任何非幺半群的零二进制操作一起使用,这就是为什么Scala的fold
很难用Clojure的fold
进行模拟的原因。如果您想要类似Scala的折叠
,请在Clojure中使用reduce
编辑
哦,等等。文件实际上说明
combinef必须是关联的,并且在调用时没有
参数(combinef)必须生成其标识元素
也就是说,我们实际上被迫使用幺半群作为combinef
,因此上面的42000,([x y]y)
-示例实际上是无效的,并且行为实际上是未定义的。我以某种方式获得了42006
这一事实是一个严格意义上的黑客行为,它依赖于库函数的未定义行为来获得所需的结果42006
考虑到这些额外的信息,我不确定Scala的fold
是否可以被Clojure的core.reducers/fold
模拟。Clojure的折叠
似乎被限制为使用幺半群的约化,而Scala的折叠更接近于一般的列表
反同构,以牺牲并行性为代价。它与Scala的折叠有何不同?这似乎在某种程度上回答了一个稍微不同的问题,这个问题更容易回答。实际的问题不是要比较Scala的fold
和Clojure的reduce
,而是要比较Clojure的fold
。你能不能明确地说,你说的是Clojure.core.reducers/fold
,这样答案就不用猜了?在clojure.core
中没有fold
(有reduce
),这至少是我从这个问题中暗示的。