【问题标题】:Why would I ever choose not to use the clojure 1.5 reducers feature?为什么我会选择不使用 clojure 1.5 reducers 功能?
【发布时间】:2023-03-28 07:08:02
【问题描述】:

我正在阅读 1.5 中引入的 clojure reducers,这里是:https://github.com/clojure/clojure/blob/master/changes.md。我的理解是,它们是对现有 map/filter/reduce 函数的性能增强。所以如果是这样的话,我想知道为什么它们在一个新的命名空间中,而不是简单地替换现有的 map/reduce/filter 实现。换句话说,我为什么选择使用新的 reducers 功能?

编辑:

针对最初的两个答案,这里澄清一下:

我将在这里引用发行说明:

Reducer 提供了一组用于处理集合的高性能函数。实际的折叠/减少算法是通过被减少的集合指定的。这允许每个集合定义最有效的方法来减少其内容。

这听起来不像新的 map/filter/reduce 函数本质上是并行的。例如,在发行说明中进一步说明:

它包含一个新函数 fold,它是一个并行 reduce+combine

因此,除非发行说明写得不好,否则在我看来,有一个新函数 fold,它是并行的,而其他函数是特定于集合的实现,旨在为特定集合产生可能的最高性能.我只是误读了这里的发行说明吗?

【问题讨论】:

  • 好问题,尽管“[W]我为什么不选择使用新的 [clojure] reducers 功能”作为一个更好的标题。
  • 感谢您的反馈,完成。
  • 这可能有助于理解为什么 reducer 不能仅仅替换旧的实现:vimeo.com/45561411

标签: clojure


【解决方案1】:

在某些情况下,它们无法替换旧的实现。例如,如果您有无限序列,或者您实际上需要对集合进行顺序处理。

【讨论】:

  • RIght,例如 (take 5 (into [] (r/map (partial str "FOO") (repeatedly #(java.util.UUID.randomUUID))))) 永远不会终止。这是你绝对想要懒惰的情况。
【解决方案2】:

前言:你有问题,你将使用并行,现在问题二有你。

从某种意义上说,它们是替代品(相对于普通的旧顺序映射等)。并非所有操作都可以并行化(在许多情况下,操作必须至少为associative,还要考虑惰性序列和迭代器)。此外,并不是每个操作都可以有效地并行化(总是有一些协调开销,有时开销大于并行化增益)。

【讨论】:

  • 感谢转发。
【解决方案3】:

我发现 Rich Hickey 写的以下文章虽然仍然有些令人困惑,但为我清除了(一些)问题:http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html

特别是总结:

通过采用另一种观点,将集合视为可简化的事物,而不是可排序的事物,我们可以获得一组互补的基本操作,在延迟与并行性之间进行权衡,同时保留相同的高级函数式编程模型。由于两个模型保持相同的形状,我们可以轻松选择适合手头任务的模型。

【讨论】:

【解决方案4】:

您可能决定不使用减速器的几个充分理由:

  • 您需要保持与 Clojure 1.4 的向后兼容性。这使得在库代码中使用 reducer 变得很棘手,例如,您不知道您将使用哪个 Clojure 版本
  • 在某些情况下,有更好的选择:例如,如果您正在处理数字数组,那么几乎可以肯定的是,改用 core.matrix 之类的东西会更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多