foldLeft v。foldRight - 这有什么关系吗? [英] foldLeft v. foldRight - does it matter?

查看:119
本文介绍了foldLeft v。foldRight - 这有什么关系吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以前, Nicolas Rinaudo 在Scala的列表foldRight总是使用foldLeft?



现在学习Haskell,我的理解是<在 :: 的情况下,code> foldRight 优先于 foldLeft prepend)可以用于 ++ (追加)。

据我所知,理由是性能 - 前者出现在 O(1)中,即添加一个项目在前面 - 恒定时间。而后者需要 O(N),即遍历整个列表并添加一个项目。



在Scala ,假设 foldLeft 是以 foldRight 的形式实现的,那么使用:+ over ++ foldRight 甚至自 foldRight 颠倒过来,然后 foldLeft'd



例如,考虑这个简单的 fold .. 操作用于简单地返回列表中的元素。



foldLeft 折叠在每个元素上,通过:+ 将每个元素添加到列表中。

 阶>列表(foo,bar)。foldLeft(List [String]()){
(acc,elem)=> acc:+ elem}
res9:List [String] = List(foo,bar)

foldRight 在每个项目上执行foldLeft并使用 :: 运算符,但是然后反转。

  scala>列表(foo,bar)。foldRight(List [String]()){
(elem,acc)=> elem :: acc}
res10:List [String] = List(foo,bar)

实际上,在Scala中使用 foldLeft foldRight 来使用给定的 foldRight 使用 foldRight

解决方案

<@> Henrichs的答案实际上与Scala无关,因为Scala对 foldLeft foldRight 的实现是完全不同的(对于初学者,Scala有急切的评价)。



foldLeft foldRight 自己对于你的程序的性能实际上很少做。两者都是(自由地说)O(n * c_f),其中c_f是给出的函数 f 的一次调用的复杂度。不过, foldRight 由于额外的反向,因此会减慢一个常数。



因此,区分彼此的真正因素是您提供的匿名函数的复杂性。有时候,编写一个有效的函数可以更容易,该函数可以用于处理 foldLeft ,有时还可以处理 foldRight 。在你的例子中, foldRight 版本是最好的,因为你给 foldRight 的匿名函数是O(1) 。相比之下,您给 foldLeft 的匿名函数是O(n)本身(摊销,这是重要的),因为 acc 从0增长到n-1,并追加到n个元素列表中的是O(n)。 是否选择 foldLeft foldRight ,但不是因为这些函数本身,而是因为匿名给他们的功能。如果两者都相同,默认情况下选择 foldLeft


Previously, Nicolas Rinaudo answered my question on Scala's List foldRight Always Using foldLeft?

Studying Haskell currently, my understanding is that foldRight should be preferred over foldLeft in cases where :: (prepend) can be used over ++ (append).

The reason, as I understand, is performance - the former occurs in O(1), i.e. add an item to the front - constant time. Whereas the latter requires O(N), i.e. go through the whole list and add an item.

In Scala, given that foldLeft is implemented in terms of foldRight, does the benefit of using :+ over ++ with foldRight even matter since foldRight gets reversed, and then foldLeft'd?

As an example, consider this simple fold.. operation for simply returning a list's elements in order.

foldLeft folds over each element, adding each item to the list via :+.

scala> List("foo", "bar").foldLeft(List[String]()) { 
                                                    (acc, elem) => acc :+ elem }
res9: List[String] = List(foo, bar)

foldRight performs a foldLeft with :: operator on each item, but then reverses.

scala> List("foo", "bar").foldRight(List[String]()) { 
                                                    (elem, acc) => elem :: acc }
res10: List[String] = List(foo, bar)

In reality, does it matter in Scala which foldLeft or foldRight to use given that foldRight uses foldRight?

解决方案

@Rein Henrichs' answer is indeed irrelevant to Scala, because Scala's implementation of foldLeft and foldRight is completely different (for starters, Scala has eager evaluation).

foldLeft and foldRight themselves have actually very little to do wrt the performance of your program. Both are (liberally speaking) O(n*c_f) where c_f is the complexity of one call to the function f that is given. foldRight is slower by a constant factor because of the additional reverse, though.

So the real factor that differentiates one from the other is the complexity of the anonymous function that you give. Sometimes, it is easier to write an efficient function designed to work with foldLeft, and sometimes to foldRight. In your example, the foldRight version is best, because the anonymous function that you give to foldRight is O(1). In contrast, the anonymous function that you give to foldLeft is O(n) itself (amortized, which is what matters here), because acc keeps growing from 0 to n-1, and appending to a list of n elements is O(n).

So it actually matters whether you choose foldLeft or foldRight, but not because of these functions themselves, but because of the anonymous functions given to them. If both are equivalent, choose foldLeft by default.

这篇关于foldLeft v。foldRight - 这有什么关系吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆