C#でProject Euler(6) 反復子ブロック

タイトルは、英語ではiterator block、日本語公式サイトでは反復子ブロックと呼んでいるようです(方法 : 整数リストの反復子ブロックを作成する (C#))。

反復子ブロックはPythonでいうジェネレータのようなものです。例としてProblem 2を考えてみましょう。

from itertools import *

def fibs():
    a, b = 0, 1
    while True:
        yield b
        a, b = b, a + b

N = 4 * 10 ** 6
print sum(f for f in takewhile(lambda f: f <= N, fibs()) if f % 2 == 0)

この問題は、フィボナッチ数列の無限列を作るのが定石ですよね。これをC#で書くとこうなります。

using System;
using System.Collections.Generic;
using System.Linq;

class e002 {
    static IEnumerable<int> fibs() {
        var a = 0;
        var b = 1;
        while(true) {
            yield return b;
            var tmp = b;
            b += a;
            a = tmp;
        }
    }
    
    static void Main(string[] args) {
        const int   N = (int)4e6;
        var s = fibs().TakeWhile(n => n < N).Where(n => n % 2 == 0).Sum();
        Console.WriteLine(s);
    }
}

ほぼ、まんまですよね。違うところは、IEnumerableを戻り値の型に指定するところと、yieldでなくてyield returnと書くところくらいです。あと、Pythonのジェネレータでreturnとするところは、yield breakとします。ちょっとややこしいですね。