Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

foldLeft v. foldRight - does it matter?

Tags:

haskell

scala

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?

like image 659
Kevin Meredith Avatar asked Jun 23 '14 16:06

Kevin Meredith


People also ask

What is foldLeft and foldRight in Scala?

The primary difference is the order in which the fold operation iterates through the collection in question. foldLeft starts on the left side—the first item—and iterates to the right; foldRight starts on the right side—the last item—and iterates to the left. fold goes in no particular order.

What is foldLeft?

foldLeft() method is a member of TraversableOnce trait, it is used to collapse elements of collections. It navigates elements from Left to Right order. It is primarily used in recursive functions and prevents stack overflow exceptions.

What is foldLeft in spark?

The Scala foldLeft method can be used to iterate over a data structure and perform multiple operations on a Spark DataFrame. foldLeft can be used to eliminate all whitespace in multiple columns or convert all the column names in a DataFrame to snake_case.

How does fold right work?

The foldRight method takes an associative binary operator function as parameter and will use it to collapse elements from the collection. The order for traversing the elements in the collection is from right to left and hence the name foldRight. The foldRight method allows you to also specify an initial value.


1 Answers

@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.

like image 113
sjrd Avatar answered Sep 23 '22 04:09

sjrd