Ramda 中 Lodash _.transform 的等价物是什么?

What is the equivalent of Lodash _.transform in Ramda?

我正在尝试学习 Ramda,但我在文档中找不到它与 Lodash _.transform 函数的等效项:

_.transform([2, 3, 4], function(result, n) {
  result.push(n *= n);
  return n % 2 == 0;
}, []);
// => [4, 9]

据我所知_.transformArray#reduce类似,只是可以打断:

_.transform([2, 3, 4], function(result, n) {
  result.push(n *= n);
  return n % 2 == 0;
}, []);
// => [4, 9]

使用 Ramda,您可以使用 reduce 做同样的事情:

The iterator function receives two values: (acc, value). It may use R.reduced to shortcut the iteration.

在 Ramda 中,上面的代码将是:

const transform =
  reduce((acc, x) =>
    (x % 2 ? reduced : identity)
      ([...acc, x * x]), []);

transform([2, 3, 4]);
//=> [4, 9]

您使用 reduced 将累加器 acc 包装在一个特殊对象中,该对象告诉 Ramda 的 reduce 函数缩短迭代。

identity函数returns其参数。例如identity(42) === 42.

基本上我在每次迭代中所做的是:

  1. 我需要什么功能? reducedidentity?
  2. 然后用 [...acc, x * x]
  3. 调用那个函数

在伪代码中:

( stop ? reduced OR identity )(next_accumulator_value)

不,如果我理解正确的话。 Ramda 可能永远不会对这种行为感兴趣。事实上,当人们试图用 Ramda 做类似的事情时,他们往往会以失败告终。 (免责声明:我是 Ramda 的核心贡献者之一。)

customcommander 指出的似乎是 Ramda 确实设法处理的 _.transform 的一个功能——提前退出。使用 reduced 使这成为可能,但我也很少使用它。

但是提供给它的函数的全部要点(lodash 术语中的 iteratee)是改变累加器对象。它的 return 将被忽略,除非您通过 returning false 发送 end the madness 信号。只有它的副作用才是真正重要的。

Ramda 是围绕避免突变而设计的。当你使用 Ramda 的 reduce 折叠到一个列表时,强烈的期望是你会使用 concat 而不是 push;换句话说,您不会改变输入。 Ramda 没有强制执行这一点,有时出于性能原因回避这种期望,但是你可能必须小心在调用之间共享累加器。但 Ramda 肯定不会让它变得更容易。任何旨在仅用于其副作用的函数都是 Ramda 的诅咒。 (请不要提醒我forEach!"A foolish consistency is the hobgoblin of little minds.")

请注意,customcommander 的回答并未尝试改变 acc 值,而是 return 编辑了一个新值:这是非常惯用的 Ramda。

另外一个非常不同的是 lodash 愿意在没有提供初始累加器的情况下创建一个初始累加器。 Ramda 不允许任何可选参数。它们只是不同的设计。


重要的一点是,没有特别的理由期望每个 lodash 函数都有一个 Ramda 等价物。 Ramda 是独立开发的,针对不同的编码风格,受制于不同的约束,并且从未设计为直接替代品。所以它与 lodash 的关系与 lodash 与 Underscore 的关系非常不同。

它们的重叠程度与它们的重叠程度一样多,这证明了两者都支持的许多功能的基本性质。当然,还有一个不可忽视的反馈循环,即人们从一个图书馆请求另一个图书馆的功能;但我认为很多功能只是被广泛需要更为重要。