Clojure Clojure.core.reducers/fold和Scala fold之间有什么区别?

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有
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
),这至少是我从这个问题中暗示的。