首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala Stream按需调用(惰性)与按名称调用

Scala Stream按需调用(惰性)与按名称调用
EN

Stack Overflow用户
提问于 2013-05-07 04:47:35
回答 2查看 1.1K关注 0票数 6

所以我知道call-by-need只是call-by-name的一个记忆版本。在Martin Odersky关于Coursera的FP课程7.3 (惰性评估)中,他提到如果Streams是使用call-by-name实现的,那么它可能会导致计算复杂性的激增。

这种井喷的例子是什么?

按名称调用:

代码语言:javascript
复制
def cons[T](hd: T, tl: => Stream[T]) = new Stream[T] {
  def head = hd
  def tail = tl
  ...
}

按需调用:

代码语言:javascript
复制
def cons[T](hd: T, tl: => Stream[T]) = new Stream[T] {
  def head = hd
  lazy val tail = tl
  ...
}
EN

回答 2

Stack Overflow用户

发布于 2013-05-08 02:43:13

例如斐波那契级数,通过添加前两个元素形成后继者来实现。如果没有记忆化,序列的长度将线性减速(和堆栈增长):

代码语言:javascript
复制
scala> lazy val fib: Stream[Int] = Stream.cons(0,
     | Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2)))
fib: Stream[Int] = Stream(0, ?)

延迟复制自this blog的示例(-sic-)

票数 2
EN

Stack Overflow用户

发布于 2022-01-13 01:11:27

deflazy val都很懒。不同之处在于,每次调用def时都会重新计算它。lazy val只在第一次被调用时被求值,并且对它的任何调用都只查看第一个求值的值。

使用def意味着每次调用tail时都要对其进行重新计算。

代码语言:javascript
复制
def randDef: () => Int = {
  val r = scala.util.Random.nextInt
  () => r
}

val randVal: () => Int = {
  val r = scala.util.Random.nextInt
  () => r
}

lazy val randLazyVal: () => Int = {
  val r = scala.util.Random.nextInt
  () => r
}
// defined function randDef
// randVal: () => Int = ammonite.$sess.cmd18$Helper$$Lambda$2545/0x00000008013a4430@7466fa3
// randLazyVal: () => Int = [lazy]

randDef()
// res8: Int = -693604502
randDef()
// res9: Int = 2056941756
randDef eq randDef
// res15: Boolean = false

randVal()
// res11: Int = 3
randVal()
// res12: Int = 3
randVal eq randVal
// res16: Boolean = true

randLazyVal()
// res13: Int = 99
randLazyVal()
// res14: Int = 99
randLazyVal eq randLazyVal
// res17: Boolean = true
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16407025

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档