『プログラミングTypeScript』 第四章 - ジェネレーターとイテレーター
『プログラミングTypeScript』の第四章ではジェネレーターおよびイテレーターに関するセクションがある。そこではフィボナッチ数を生成するジェネレーターを返す関数 (ジェネレーター関数) が例示されている。
本記事では「素数を生成するジェネレーター」を返す関数を書いてみよう。素数は無限に存在するので、次の素数を返せるというのはジェネレーターの用途として適切だろう。
function *createPrimeGenerator() {
const primes = new Set<number>()
let current = 2
while (true) {
while (true) {
let isPrime = true
for (const prime of primes) {
if (current % prime === 0) {
isPrime = false
break
}
}
if (!isPrime) {
current++
continue
}
primes.add(current)
break
}
yield current++
}
}
const primeGenerator = createPrimeGenerator()
for (let i = 0; i < 100; i++) {
console.log(primeGenerator.next())
}
関数名の前に *
をつけることでジェネレーター関数を定義できる。ジェネレーター関数はジェネレーター (Generator
) を返し、その値は yield
キーワードで生成される。利用者は next()
をコールすることでジェネレーターに次の値を要求できる。
ジェネレーターとイテレーター
createPrimeGenerator()
が返す値はジェネレーターだが、イテレーターでもある。もっと言えば、反復可能なイテレーターでもある。
『プログラミングTypeScript』から「反復可能オブジェクト」と「イテレーター」の定義を引用しよう。
反復可能オブジェクト:
Symbol.iterator
と呼ばれるプロパティを含んでいるオブジェクト。このプロパティの値は、イテレーターを返す関数。イテレーター:
next
と呼ばれるメソッドを定義しているオブジェクト。このnext
メソッドはvalue
およびdone
というプロパティを持つオブジェクトを返す。
ここで IDE (IntelliJ IDEA) は先ほどの例での primeGenerator.
の補完を次のように表示してくる。
System.iterator
と next
の両方を持つことがわかる。したがって、これは反復可能なイテレーターだと言える。