3

Martin Odersky の著書「Programming in Scala」には、関数 fibFrom に引数として渡された 2 つの数値から始まるフィボナッチ数列を計算する例があります。

def fibFrom(a: Int, b: Int): Stream[Int] =
       a #:: fibFrom(b, a + b)

メソッド take() をこの再帰関数に適用すると、次のようになります。

fibFrom(1, 1).take(15).print

出力は次のようになります。

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, empty

この出力は経験豊富な人にとっては明らかかもしれませんが、このメソッド take() がストリームをさらに計算する方法を正確に理解していません。15 はどういうわけか非自明に fibFrom() に渡されますか?

4

2 に答える 2

3

Stream指摘すべきことは、遅延評価されることだと思います:

クラス Stream は、要素が必要な場合にのみ評価される遅延リストを実装します。

scala-lang.orgから引用

fibFrom関数は を返しているStreamので、関数が呼び出されても何もしないことがわかります。にアクセスしようとしたときにのみ、数値の計算が開始されますStream
takefunction も a を返し、Stream遅延して動作します。
このprint関数は、実際に再帰を呼び出し、出力に15個の数字を入力すると停止する関数です(例のように)。

これは、関数を 1 つずつ実行して出力を確認することで簡単に確認できます。
Lets run only fibFrom: 戻り値が aで、数値がまだ計算されていないことがわかります。
ここに画像の説明を入力
Stream

最初のテスト と同じです take(15)
ここに画像の説明を入力

最終的に、実行するprintと望ましい結果が得られるため、実際fibFromには 15 個の数値に達するまで再帰的に実行されます。
ここに画像の説明を入力

おまけ:ストリームを非遅延データ構造に変換すると、計算がトリガーされます。
ここに画像の説明を入力

于 2020-03-27T12:19:38.503 に答える