Scala 的 val 遞歸定義

還是在上次提到的知乎回答《一行 Scala 能實(shí)現(xiàn)怎樣喪心病狂的代碼》https://www.zhihu.com/question/51038841/answer/123883134?中,有使用遞歸定義的 val 的斐波那契數(shù)列和質(zhì)數(shù)的實(shí)現(xiàn):
斐波那契數(shù)列
質(zhì)數(shù)
學(xué)習(xí)過(guò)程中發(fā)現(xiàn),使用 REPL 顯然是可以成功運(yùn)行的,畢竟答主就是使用的 REPL。

但是在我自己平時(shí)使用的 object main 方法內(nèi)寫下如下代碼,編譯就會(huì)報(bào)錯(cuò):
代碼本身在 IDEA 中并不會(huì)報(bào)錯(cuò),但是執(zhí)行編譯時(shí)會(huì)報(bào)錯(cuò) “`forward reference extends over definition of value fib`”

看報(bào)錯(cuò)的內(nèi)容,大致是指我們?cè)诙x時(shí)使用 `fib` 的時(shí)候(即 `fib.scanLeft` 處)`fib` 本身還沒(méi)有定義好。那么經(jīng)過(guò)我的嘗試,發(fā)現(xiàn)如果想要不報(bào)錯(cuò),正常運(yùn)行,有三種修改方法:
可以參考 StackOverflow 上的一則討論 《Scala recursive val function inside val》(https://stackoverflow.com/questions/66409638/scala-recursive-val-function-inside-val)?
1. 將 `val fib` 和 `val primes` 提到 object 的大括號(hào)中,即:
2. 在 `val fib` 和 `val primes` 前面加上 `lazy`
3. 將 `val fib` 和 `val primes` 改為 `def fib` 和 `def primes`
方法是實(shí)驗(yàn)出來(lái)了,但是對(duì)應(yīng)的原理卻不太好解釋。
首先是 3 相對(duì)比較好理解,遞歸的方法自然是沒(méi)有問(wèn)題的。
其次是 2 使用 `lazy` 關(guān)鍵字,讓變量惰性加載,賦值后面的語(yǔ)句(`0 #:: fib.scanLeft(1)(_ + _)`)在 `fib` 第一次使用(`fib.take(10).toList`)時(shí)才真正執(zhí)行,也相對(duì)好理解。
奇怪的是,為什么遞歸 val 定義在 main 方法內(nèi)就會(huì)報(bào)錯(cuò),而 object 以及 REPL 中就可以正常編譯呢?這個(gè)問(wèn)題有待進(jìn)一步學(xué)習(xí)與研究。