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

斯卡拉:流动不懒惰?

发布时间:2020-12-16 09:17:18 所属栏目:安全 来源:网络整理
导读:我知道溪流应该是 Scala中的懒惰评估序列,但是我认为我正在遭受某种根本的误解,因为它们似乎比我预料的更加渴望. 在这个例子中: val initial = Stream(1) lazy val bad = Stream(1/0) println((initial ++ bad) take 1) 我得到一个java.lang.ArithmeticExce
我知道溪流应该是 Scala中的懒惰评估序列,但是我认为我正在遭受某种根本的误解,因为它们似乎比我预料的更加渴望.

在这个例子中:

val initial = Stream(1)
 lazy val bad = Stream(1/0)
 println((initial ++ bad) take 1)

我得到一个java.lang.ArithmeticException,这似乎是由零除法引起的.我会期望不会得到评估,因为我只是从流中要一个元素.怎么了?

解决方法

好的,所以在评论其他答案后,我想我可以把我的意见变成一个正确的答案.

流确实是懒惰的,只会根据需要计算其元素(您可以使用#::按元素构造流元素,很像:: for List).例如,以下不会抛出任何异常:

(1/2) #:: (1/0) #:: Stream.empty

这是因为当应用#::时,尾部按名称传递,以便不要热切地评估它,但只有在需要时(请参阅Cons.Wrapper.#:: const.apply和Stream.scala中的类缺点以获取更多详细信息).
另一方面,头脑是通过价值的,这意味着它总是被热切地评估,无论什么(如Senthil所提到的).这意味着执行以下操作实际上会抛出一个ArithmeticException:

(1/0) #:: Stream.empty

这是一个值得了解流的东西.但是,这不是您面临的问题.

在你的情况下,算术异常发生在甚至实例化单个流之前.当在lazy val bad = Stream(1/0)中调用Stream.apply时,该参数被强制执行,因为它不被声明为by name参数. Stream.apply实际上需要一个vararg参数,而这些参数必须通过值传递.即使它被名字传递,ArithmeticException将不久之后被触发,因为如前所述,Stream的头部总是被早期评估.

(编辑:李大同)

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

    推荐文章
      热点阅读