200*_*ess 0 scala compiler-errors forward-reference lazy-sequences
我正在尝试使用Scala 2.11.7编译以下代码.
object LucasSeq {
val fibo: Stream[Int] = 0 #:: 1 #:: fibo.zip(fibo.tail).map { pair =>
pair._1 + pair._2
}
def firstKind(p: Int, q: Int): Stream[Int] = {
val lucas: Stream[Int] = 0 #:: 1 #:: lucas.zip(lucas.tail).map { pair =>
p * pair._2 - q * pair._1
}
lucas
}
}
Run Code Online (Sandbox Code Playgroud)
fibo基于Scala Stream文档中的Fibonacci序列示例,它可以工作.
但是,firstKind试图用参数推广序列p和q(制作第一类Lucas序列)的函数有以下错误:
LucasSeq.scala:7: error: forward reference extends over definition of value lucas
val lucas: Stream[Int] = 0 #:: 1 #:: lucas.zip(lucas.tail).map { pair =>
^
one error found
Run Code Online (Sandbox Code Playgroud)
它基本上是相同的代码,为什么它在函数外部工作但不在函数内部?
这个错误信息困扰了我之前的许多程序员.我考虑过......
implicit val lucas - 没有帮助.-Xprint:typer诊断程序进行编译 - 不确定如何处理该信息.我可能会继续阅读几个小时,但我认为最好在此时寻求帮助.我正在寻找解决方案和解释.(我熟悉函数式编程,但对Scala不熟悉,所以如果解释涉及"合成"和"隐式"等术语,那么我可能还需要对其进行额外的解释.)
这里有一个答案,但由于某种原因它被删除了.
基本上有两种选择.你可以让你val进入lazy val.或者您可以将lucas: Stream[Int]类定义为字段.您可以使用构造函数p和q在构造函数中参数化类.
你是对的,原始代码是懒惰的.但scala翻译它并不够懒惰.
为了简单起见,请考虑val a = 1 + a将要翻译的代码(我知道代码没有多大意义).在Java int a = 1 + a中将无法正常工作.Java将尝试使用a中1 + a,但a还没有被初始化.即使Java已经Integer a = 1 + a并且a将成为引用,Java仍然无法执行此操作,因为Java 1 + a在分配时运行语句a
所以它给我们留下了两个选择.a不是作为变量定义,而是作为字段定义.Scala通过定义递归方法而不是字段来自动解决问题 - 因为scala中的字段无论如何都是两个方法+变量.或者你可以通过指定你的val来明确地告诉scala它应该解决这里的延迟问题lazy val.这将使scala生成一个隐藏类,其中包含所有必需的基础结构,使其变得懒惰.
您可以通过使用-print选项运行编译器来检查此行为.但输出相当复杂,尤其是lazy val以防万一.
另请注意,因为您的信息流离开了范围,而且您的信息流还有两个参数 - p而且q,如果您选择使用,则每次调用都会重新计算您的信息流lazy val.如果您选择创建一个额外的类 - 您可以通过为每个类p和q可能的高速缓存此类的所有实例来控制它
PS在Java这里说我当然是指JVM.从Java的角度来看,它更容易思考
| 归档时间: |
|
| 查看次数: |
964 次 |
| 最近记录: |