在浏览Functional Programming in Scala时,我遇到了以下代码段:
def foldRight[A](z: => B)(f: (A,=>B) => B):B = uncons match {
case Some((h,t)) => f(h,t.foldRight(z)(f))
case None => z
}
然后,作者继续说明以下内容:
这看起来非常类似于我们为List写的foldRight,但是 注意我们的组合函数f在第二个函数中是非严格的 参数。如果f选择不评估其第二个参数,这个 尽早终止遍历。我们可以通过使用foldRight来看到这一点 实现exists,它检查Stream中是否有任何值 匹配给定的谓词。
然后作者陈述如下:
def exists(p: A => Boolean): Boolean =
foldRight(false)((a, b) => p(a) || b)
我的问题是组合函数f如何导致exists方法的提前终止?我认为我无法理解文本中的情况。
答案 0 :(得分:6)
在f(h,t.foldRight(z)(f))
中,提供给f
的第一个参数是h
,第二个参数是t.foldRight(z)(f)
。定义foldRight
的方式是它的f
参数的第二个参数是一个名字参数,在需要之前不会进行评估(并且每次需要时都会进行评估)。所以在f: (A, =>B) => B
中,类型A
的第一个参数是普通参数,但类型B
的第二个参数是一个名字参数。
所以假装你这样定义f
:
f(a: A, b: => Boolean): Boolean = predicate(a) || b
如果predicate(a)
为真,则永远不需要b
,永远不会对其进行评估。这就是或运算符的工作方式。
所以说适用于某些exists
的{{1}}。对于第一个元素,将存在(其中Stream
为真)此代码:
p(h)
与此代码相同(我们假设我们有一个非空流,所以我们可以删除第二种情况):
uncons match {
case Some((h,t)) => f(h,t.foldRight(z)(f))
case None => z
}
这相当于(展开f(h,t.foldRight(z)(f))
):
f
但是p(h) || t.foldRight(z)(f)
是真的,所以:
p(h)
这与true || t.foldRight(z)(f)
相同,无需继续调用true
,因此提前终止!