代码之家  ›  专栏  ›  技术社区  ›  Ertuğrul Çetin

Clojure和clojure.core.reducers/折叠斯卡拉褶皱呢?

  •  2
  • Ertuğrul Çetin  · 技术社区  · 6 年前

    我发现Clojure clojure.core.reducers/fold 功能。

    fold 功能,但不能理解他们的工作方式是否不同?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Andrey Tyukin    6 年前

    我猜你说的是 clojure.core.reducers/fold .

    Scala的默认值 fold 序列的实现非常简单:

    collection.fold(identityElem)(binOp)
    

    只是从 identityElem 然后依次遍历集合,并应用二进制操作 binOp 对于已经累积的结果和当前序列值,例如。

    (1 to 3).fold(42000)(_ + _)
    

    将导致 42000 + 1 + 2 + 3 42006 .

    折叠

    (r/fold n combinef reducef coll)
    

    从上述工程包并行分为两个阶段。首先,它将输入分成更小的大小组 n (大约),然后使用 reducef ,最后使用 combinef .

    主要区别在于 同时使用二进制(Clojure具有多进制函数),以及 (combinef) (不带参数)将被调用为每个分区生成标识元素(因此, this documentation this documentation 谎言)。

    也就是说,为了从上面的例子中模拟Scala的折叠,我们必须这样写:

    (require '[clojure.core.reducers :as r])
    
    (r/fold 3 (fn ([] 42000) ([x y] y)) + [1 2 3])
    

    一般来说,斯卡拉 折叠

    collection.fold(identityElement)(binOp)
    

    reducers/fold 具体如下:

    (r/fold collectionSize (fn ([] identityElem) ([x y] y)) binOp collection)
    

    (注意 ([x y] y)

    用Clojure的 折叠 . 如果你想要像Scala那样的东西 折叠 ,使用 reduce 在Clojure。


    编辑

    哦,等等。文件上说

    参数(combinef)必须产生其标识元素

    也就是说,我们实际上 组合F ,所以 42000, ([x y] y) -示例实际上是无效的,行为实际上是未定义的。事实上我得到了 出去是个好主意 在严格的技术意义上,它依赖于库函数的未定义行为来获得期望的结果 42006 .

    折叠 core.reducers/fold 完全。Clojure的 折叠 似乎受限于幺半群的约化,而Scala的折叠更接近于一般的 List 以牺牲平行性为代价的变形。

        2
  •  2
  •   Alan Thompson    6 年前

    这个 clojure.core.reducers

    https://clojure.org/reference/reducers .

    (r/fold reducef coll)
    (r/fold combinef reducef coll)
    (r/fold n combinef reducef coll)
    

    大约n个(默认512个)元素。每组使用 reducef函数。reducef函数将在没有 用于在每个分区中生成标识值的参数。结果 然后使用combinef(默认为 reducef)函数。当不带参数调用时,(combinef)必须


    在你把你的机器发挥到极致之前,你应该坚持基本原则 reduce 功能:

    https://clojuredocs.org/clojure.core/reduce

    fold 功能:

    (reduce + 0 [1 2 3 4 5]) => 15
    

    其中函数签名为:

    (reduce <op> <init-val> <collection-to-be-reduced> )