これは、Visual Basic Advent Calendar 2012 12/7日の記事。
今回、Yieldを使ってフィナボッチ数列を作成してみます。
以前、静岡Developers勉強会で「Haskell」を勉強した際に、「無限リスト」を習いました。
無限リストとは、上限を決めないで無限に続くリストのことです。
無限リストを用いることで、手作業で作成しなくてもルールを与えるだけでシーケンスを生成することが可能である。
最も単純な例では自然数のシーケンスで「1,2,3,4・・・」となります。これをHaskellでは[1..]と表記できます。
また、Haskellでは等差数列くらいなら簡易的に表記することができます。
>[1, 9..]
[1,9,17,25,33,41,49,57,65,73,81,89,97・・・]
等差数列くらいのルールなら簡易表記できますが、階乗、素数、フィナボッチ数列などはそれなりにプログラムを組む必要があります。
今回、無限リストのフィナボッチ数列を作成するために、無限ループを用いました。
また、表示する際には無限リストから10個取得するようにしています。
さて、このプログラムの結果は、1行目のlist変数に格納するところでエラーとなり、次の行の10個取得する処理まで動作しません。
これは、list変数に格納する前に計算処理を行う「先行評価」の方式となっているからです。
Module Test
Sub Main()
Dim list = fibonacci()
Dim fibList = From n In list Take (10)
For Each number As Integer In fibList
Console.Write(number & " ")
Next
'Output: 0,1,1,2,3,5,8,13,21,34
Console.ReadLine()
End Sub
'フィナボッチ数列
Private Function fibonacci() As List(Of Integer)
Dim a As Integer = 1
Dim b As Integer = 1
Dim result As List(Of Integer) = New List(Of Integer)
result.Add(0)
While True
result.Add(a)
a = a + b
result.Add(b)
b = b + a
End While
Return result
End Function
End Module
今度は、Yieldを使ってみます。
先程と同様、無限リストのフィナボッチ数列を作成するために無限ループを用いております。
result.AddのところをYieldに変更しました。
また、Yieldを使うためにFunctionの前にIteratorを付け、戻りの型はIEnumerableに変更してあります。
今度は、正常に結果が表示されるようになりましたね。
これは、必要になった時に計算される「遅延評価」となっているからです。
'フィナボッチ数列
Private Iterator Function fibonacci() As System.Collections.IEnumerable
Dim a As Integer = 1
Dim b As Integer = 1
Yield 0
While True
Yield a
a = a + b
Yield b
b = b + a
End While
End Function
このようにYieldを使用することで、無限リストを生成することができます。
次回は、Yieldの特徴を利用して簡易ゲームを作成してみます。