【问题标题】:In Scala, when is it necessary to specify laziness?在 Scala 中,什么时候需要指定惰性?
【发布时间】:2020-08-10 14:36:19
【问题描述】:

在本地 Scala REPL 中,可以在不使用关键字 lazy 的情况下定义流和惰性列表。

scala> val fibo: LazyList[BigInt] = (0: BigInt) #:: (1: BigInt) #:: fibo.zip(fibo.tail).map { n => n._1 + n._2 }
fibo: LazyList[BigInt] = LazyList(<not computed>)

scala> fibo(100)
res17: BigInt = 354224848179261915075

scala> val prime: LazyList[Int] = 2 #:: LazyList.from(3).filter(i => prime.takeWhile {
     |    j => j * j <= i
     | }.forall {
     |    k => i % k != 0
     | })
prime: LazyList[Int] = LazyList(<not computed>)

scala> prime(100)
res18: Int = 547

这在Stream 和 Scastie 中的工作方式大致相同。它也应该在 IntelliJ 项目中工作,对吧?

  @Test def testGCDConsecutivePrimeNumbers(): Unit = {
    val prime: LazyList[Int] = 2 #:: LazyList.from(3).filter(i => prime.takeWhile {
      j => j * j <= i
    }.forall {
      k => i % k != 0
    })
    for (n <- 1 to 100) {
      assertEquals(1, gcd(prime(n), prime(n + 1)))
    }
  }

  @Test def testGCDConsecutiveEvenFibonacciNumbers(): Unit = {
    val fibo: LazyList[Int] = 0 #:: 1 #:: fibo.zip(fibo.tail).map(n => n._1 + n._2)
    for (i <- 0 to 42 by 3) {
      assertEquals(2, gcd(fibo(i), fibo(i + 3)))
    }
  }

除非它没有。

错误:(21, 67) 前向引用扩展了值 prime 的定义

val prime: LazyList[Int] = 2 #:: LazyList.from(3).filter(i =&gt; prime.takeWhile {

错误:(32, 43) 前向引用扩展了值 fibo 的定义

val fibo: LazyList[Int] = 0 #:: 1 #:: fibo.zip(fibo.tail).map(n =&gt; n._1 + n._2)

将它们标记为惰性可以清除错误。

我了解 REPL 中有些事情的工作方式有所不同,但我不明白为什么这是其中之一。而且我可能在这里遗漏了一些微妙之处,但是为什么在 REPL 中省略“lazy”不会导致前向引用错误。一般来说,什么时候需要明确指定惰性,为什么?

【问题讨论】:

    标签: scala lazy-evaluation


    【解决方案1】:

    这不是直接“在 REPL 中工作方式不同”的“其中之一”,而是因为它们。在失败的代码中,prime 和 fibo 是局部变量。当您直接在 REPL 中定义它们时,它们是匿名对象的属性,即它会生成类似

    object Line1 {
      val fibo = ...
    }
    import Line1.fibo
    

    如果您查看规范,the forward reference restriction 仅适用于局部变量:

    它可以构成对象或类定义的一部分,也可以是块的局部...

    但是,在块中

    的前向引用存在限制

    【讨论】:

      猜你喜欢
      • 2011-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      相关资源
      最近更新 更多