[英]Scala lazy val explanation
我正在使用Coursera中的Scala課程中的函數式編程,我很難理解這段代碼片段 -
def sqrtStream(x: Double): Stream[Double] = {
def improve(guess: Double): Double = (guess+ x/ guess) / 2
lazy val guesses: Stream[Double] = 1 #:: (guesses map improve)
guesses
}
當我做sqrtSteam(4).take(10).toList時,這種方法會以遞增的准確度順序找到10個近似4的平方根。
有人可以在這里解釋猜測的評估策略嗎? 我懷疑當猜測的第二個價值被提升時,猜測的價值取代了什么?
讓我們從簡化的例子開始:
scala> lazy val a: Int = a + 5
a: Int = <lazy>
scala> a
stack overflow here, because of infinite recursion
所以a
重新計算直到它得到一些穩定的值,就像這里:
scala> def f(f:() => Any) = 0 //takes function with captured a - returns constant 0
f: (f: () => Any)Int
scala> lazy val a: Int = f(() => a) + 5
a: Int = <lazy>
scala> a
res4: Int = 5 // 0 + 5
你可以用def f(f: => Any) = 0
替換def f(f:() => Any) = 0
,所以a
定義看起來像是真的傳遞給了f: lazy val a: Int = f(a) + 5
。
流使用相同的機制 - guesses map improve
將作為名稱傳遞的參數傳遞(並且鏈接到懶惰a
lambda將保存在Stream中,但是直到請求尾部才計算),所以它就像lazy val guesses = #::(1, () => guesses map improve)
。 當你調用guessess.head
- 不會評估tail; guesses.tail
將懶惰地返回Stream (improve(1), ?)
guesses.tail.tail
Stream (improve(1), ?)
, guesses.tail.tail
將是Stream(improve(improve(1)), ?)
guesses.tail.tail
Stream(improve(improve(1)), ?)
等等。
您可以通過修改map函數輕松找出正在發生的事情,如scaladoc示例中所述 :
scala> def sqrtStream(x: Double): Stream[Double] = {
| def improve(guess: Double): Double = (guess + x / guess) / 2
| lazy val guesses: Stream[Double] = 1 #:: (guesses map {n =>
| println(n, improve(n))
| improve(n)
| })
| guesses
| }
sqrtStream: (x: Double)Stream[Double]
輸出是:
scala> sqrtStream(4).take(10).toList
(1.0,2.5)
(2.5,2.05)
(2.05,2.000609756097561)
(2.000609756097561,2.0000000929222947)
(2.0000000929222947,2.000000000000002)
(2.000000000000002,2.0)
(2.0,2.0)
(2.0,2.0)
(2.0,2.0)
res0: List[Double] = List(1.0, 2.5, 2.05, 2.000609756097561, 2.0000000929222947, 2.000000000000002, 2.0, 2.0, 2.0, 2.0)
guesses
的價值不是替代的。 流類似於列表,但僅在需要時才對其元素進行評估,然后將其存儲,因此下次訪問它們時,評估將不再必要。 對流本身的引用不會改變。
在示例Αλεχει上寫道,Scala API中有一個很好的解釋: http : //www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.