LoginSignup
4
4

More than 5 years have passed since last update.

JavaScriptでもジェネレーター関数

Posted at

ジェネレーター関数は説明が難しいが、一言で言うと「値を小出しに返す関数(を作る関数)」。Pythonでは例えばこう使える。イタレータを作る関数と言っても良いかも。

def firstn(n):
    num = 0
    while num < n:
        yield num
        num += 1

gen = firstn(10)

print gen.next() # —> 0
print gen.next() # —> 1
print gen.next() # —> 2
…
print gen.next() # —> 11回目は StopIteration 例外が起きる

当然、forループやリスト内包表記でも使える。

for n in firstn(10):
    print n,
# —> 0 1 2 3 4 5 6 7 8 9

print [n for n in firstn(10)]
# -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

で、このジェネレータ関数をJavaScriptでも使えるようになるらしい。正式にはES6 (ECMAScript version 6)で規格化される予定だが、幾つかの実装は既にこの機能を取り入れ始めている。

Node.jsも次の安定版v0.12で正式採用すべく、v0.11でジェネレータが使えるようになっている。で、それを使ってみた。

まず上の例をJavaScriptで書きなおし。

firstn = function* (n) {
    var num = 0
    while (num < n) {
        yield num
        num += 1
    }
};

gen = firstn(10);

console.log(gen.next()); // —> { value: 0, done: false }
console.log(gen.next()); // —> { value: 1, done: false }
console.log(gen.next()); // —> { value: 2, done: false }
…
console.log(gen.next()); // —> 11回目は { value: undefined, done: true } が返る

Pythonと違うのは値が返るのではなく、valueとdoneという二つのattributeを持つobjectが返るということ。繰り返しが終わったときには例外を発生させるのではなく、doneがtrueになる。

なお実行時には node —harmony とする。”Harmony”はES6のコードネームらしい。

そしてこれもforループで使える

for (n of firstn(10)) {
    process.stdout.write(n + " ");
}
// —> 0 1 2 3 4 5 6 7 8 9 

ES6ではリスト内包表記も使えるようになるらしいのだが、現在の最新版 (0.11.9)では未サポート。残念。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4