懒惰的折扣,提前终止混乱

问题描述 投票:7回答:1

在浏览qazxsw poi时,我遇到了以下代码片段:

Functional Programming in Scala

然后,作者继续说明以下内容:

这看起来非常类似于我们为List编写的foldRight,但请注意我们的组合函数f在其第二个参数中是非严格的。如果f选择不评估其第二个参数,则会提前终止遍历。我们可以通过使用foldRight来实现exists来检查这一点,它检查Stream中的任何值是否与给定的谓词匹配。

然后作者陈述如下:

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 
}

我的问题是组合函数f如何导致exists方法的提前终止?我不认为我能够理解文本中的情况。

scala functional-programming lazy-evaluation fold
1个回答
6
投票

def exists(p: A => Boolean): Boolean = foldRight(false)((a, b) => p(a) || b) ,提供给f(h,t.foldRight(z)(f))的第一个论点是f,第二个论点是ht.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。对于将要存在的第一个未解决的元素(其中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,因此提前终止!

© www.soinside.com 2019 - 2024. All rights reserved.