加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – Lazy foldRight提前终止混乱

发布时间:2020-12-16 19:16:58 所属栏目:安全 来源:网络整理
导读:在浏览 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 } 然后,作者继续说明以下内容: This looks very similar to the
在浏览 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 
}

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

This looks very similar to the foldRight we wrote for List,but
notice how our combining function,f,is non-strict in its second
parameter. If f chooses not to evaluate its second parameter,this
terminates the traversal early. We can see this by using foldRight to
implement exists,which checks to see if any value in the Stream
matches a given predicate.

然后作者陈述如下:

def exists(p: A => Boolean): Boolean =
  foldRight(false)((a,b) => p(a) || b)

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

解决方法

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

所以假装你定义了这样的:

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

如果谓词(a)为真,则永远不需要b,永远不会对其进行评估.这就是或操作符的工作方式.

所以说适用于某些Stream的存在.对于将存在的第一个元素(其中p(h)为真),此代码:

uncons match {
  case Some((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)

这是正确的,不需要继续调用foldRight,所以提前终止!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读