2016-11-27 117 views
4

我想学习函数式编程和Scala,所以我正在阅读Chiusano和Bjarnason的“Scala函数式编程”。在遇到列表时,我无法理解折叠方式和折叠方式。我在这里环顾四周,但我没有找到一些初学者友好的东西。因此,通过这本书提供的代码是:Scala向右折叠并向左折叠

def foldRight[A,B](as: List[A], z: B)(f: (A, B) => B): B = as match { 
    case Nil => z 
    case Cons(h, t) => f(h, foldRight(t, z)(f)) 
} 

def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match { 
    case Nil => z 
    case Cons(h,t) => foldLeft(t, f(z,h))(f) 
} 

凡缺点和无是:

case class Cons[+A](head: A, tail: List[A]) extends List[A] 
case object Nil extends List[Nothing] 

那么你实际上倍左右吗?为什么需要作为“实用”方法?还有很多其他方法使用它们,我也很难理解它们,因为我没有那两个。

+0

看看下一个线程。 http://stackoverflow.com/questions/24370549/foldleft-v-foldright-does-it-matter关于这些操作有很多信息。看起来像对我来说是重复的。 – Pavel

+0

在这个问题中,用户似乎对手头的事情有了很好的理解,我不这么认为,这是我想要帮助的。 – jrsall92

+2

对于您提供的代码。你有什么具体的问题吗?究竟是什么造成了困难?句法 ?理解差异的关键是在这两种情况下递归调用的方式。这不一样。阅读关于尾递归。希望这会有所帮助。更多链接:https://oldfashionedsoftware.com/2009/07/10/scala-code-review-foldleft-and-foldright/ – Pavel

回答

7

根据我的经验,锻炼的最佳途径直觉就是看它是如何工作的非常简单的例子之一:

List(1, 3, 8).foldLeft(100)(_ - _) == ((100 - 1) - 3) - 8 == 88 
List(1, 3, 8).foldRight(100)(_ - _) == 1 - (3 - (8 - 100)) == -94 

正如你所看到的,​​只是传递了列表的元素以及先前应用于第二个括号中的操作的结果。 还应该提到的是,如果将这些方法应用于同一个列表,只有在应用操作是关联的情况下,它们才会返回相同的结果。

+0

我认为你的操作意味着'(_ - _)',即减号而不是加号。否则,对于foldLeft和foldRight之间的区别是非常好的解释。 – melston

1

假设你有一个数字列表,并且你想把它们全部加起来。你会怎么做? 你加上第一个和第二个,然后把结果加到第三个,把结果加到第四个,等等。

这就是你要做的。

List(1,2,3,4,5).foldLeft(0)(_ + _) 

的“+”是要应用,第一个操作数是其应用的元素的结果,到目前为止,第二个操作数是下一个元素的功能。 由于您对第一个应用程序没有“迄今为止的结果”,因此您提供了一个起始值(在此情况下为0),因为它是用于添加的标识元素。

说你要乘以所有列表中的元素,带折叠,那会是

List(1,2,3,4,5).foldLeft(1)(_ * _) 

折都有它自己的Wikipedia page,你可能要检查。

当然,还有对于foldLeftfoldRight的ScalaDoc条目。