7

在 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 方法提前终止?我不认为我能够从文本中理解这是如何发生的。

4

1 回答 1

7

f(h,t.foldRight(z)(f))中,提供给的第一个参数fh,第二个参数是t.foldRight(z)(f)。定义的方式foldRight是它的参数的第二个f参数是一个按名称的参数,在需要之前不会被评估(并且每次需要时都会被评估)。所以在 中f: (A, =>B) => B,type 的第一个参数A是普通参数,而 type 的第二个参数B是按名称参数。

所以假设你f是这样定义的:

f(a: A, b: => Boolean): Boolean = predicate(a) || b

如果predicate(a)为真,则b永远不需要并且永远不会被评估。这就是or运算符的工作方式。

所以说exists适用于一些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)

这与 just 相同,true无需继续调用foldRight,因此会发生提前终止!

于 2013-06-27T06:44:17.920 回答