TypeScript - イテレータとジェネレータ

こんにちは、未来のプログラミングスーパースター!TypeScriptの興味深い世界にようこそ。ここでは、イテレータとジェネレータの魔法の領域を探求します。これらの用語が現在未知の技術のように聞こえるかもしれませんが、このチュートリアルの終わりまでに、プロのように使えるようになるでしょう!では、腕をまくって潜りましょう!

TypeScript - Iterators and Generators

イテレータ

想象して見てください。異なるおもちゃが詰まったトイボックスがあります。イテレータは、トイボックスを床に全部倒さずに、一つ一つおもちゃを手に取る魔法の杖のようなものです。すごいでしょう?それでは、TypeScriptでこれはどのように動作するか見てみましょう!

イテレータとは?

イテレータは、シーケンスの次のアイテムを返すnext()メソッドを定義したオブジェクトです。アイテムがもはや存在しない場合、シーケンスが終了したことを示す特別な値を返します。

それでは、最初のイテレータを作成してみましょう:

function createNumberIterator() {
let n = 0;
return {
next: function() {
n += 1;
if (n <= 5) {
return { value: n, done: false };
}
return { value: undefined, done: true };
}
};
}

const numberIterator = createNumberIterator();
console.log(numberIterator.next()); // { value: 1, done: false }
console.log(numberIterator.next()); // { value: 2, done: false }
console.log(numberIterator.next()); // { value: 3, done: false }
console.log(numberIterator.next()); // { value: 4, done: false }
console.log(numberIterator.next()); // { value: 5, done: false }
console.log(numberIterator.next()); // { value: undefined, done: true }

この例では、1から5までを数えるイテレータを作成しています。next()を呼ぶたびに、次の番号を返します。5に達すると、{ value: undefined, done: true }を返して終了を示します。

イテレータを使ったfor...ofループ

TypeScriptは、for...ofループを使ってイテレータをより簡単に使えるようにしています。それを見てみましょう:

function* numberGenerator() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}

for (const num of numberGenerator()) {
console.log(num);
}
// 出力:
// 1
// 2
// 3
// 4
// 5

このfor...ofループは、自動的にイテレータを使ってすべての値を通過します。トイボックスからおもちゃを一つ一つ拾ってくれるロボットアシスタントを持っているようなものです!

ジェネレータ

それでは、ジェネレータについて話しましょう。イテレータが魔法の杖なら、ジェネレータはそれをより少ない労力で作れる魔法使いのようなものです!

ジェネレータとは?

ジェネレータは、値のシーケンスを随時生成するための特別な関数で、一時停止して再開することできます。

それでは、最初のジェネレータを作成してみましょう:

function* countToFive() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}

const generator = countToFive();
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3
console.log(generator.next().value); // 4
console.log(generator.next().value); // 5
console.log(generator.next().value); // undefined

この例では、countToFiveはジェネレータ関数です。yieldキーワードは、「次の値をここで返し、この後で一時停止しよう」と言うようなものです。next()を呼ぶたびに、関数はyieldに達するまで実行され、その値を返して一時停止します。

ジェネレータを使ったループ

ジェネレータはループと組み合わせることでさらに強力になります。例を見てみましょう:

function* evenNumbersUnder20() {
for (let i = 2; i < 20; i += 2) {
yield i;
}
}

for (const num of evenNumbersUnder20()) {
console.log(num);
}
// 出力:
// 2
// 4
// 6
// 8
// 10
// 12
// 14
// 16
// 18

このジェネレータは20未満の偶数を生成します。智能的なおもちゃのディスペンサーのように、特定のタイプのおもちゃだけを渡すようなものです!

イテレータとジェネレータの違い

イテレータとジェネレータの動作を見てきましたので、主要な違いを整理してみましょう:

機能 イテレータ ジェネレータ
定義 next()メソッドを持つオブジェクト *シンボルを持つ関数
状態管理 手動 自動
作成の容易さ もっと複雑 よりシンプル
一時停止/再開 標準では非対応 yieldキーワードで内蔵
メモリ効率 大データセットに対してより効率的 大または無限のシーケンスに対して非常に効率的

イテレータは、おもちゃロボットをからだから作るようなもので、すべての詳細を定義する必要があります。一方、ジェネレータは、簡単にカスタマイズできるプレビルドロボットのようなものです。どちらもそれぞれの場面や用途があります!

実世界の例

最後に、楽しい実世界の例で学んだことをまとめましょう:

function* fibonacciGenerator() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}

const fib = fibonacciGenerator();
for (let i = 0; i < 10; i++) {
console.log(fib.next().value);
}
// 出力:
// 0
// 1
// 1
// 2
// 3
// 5
// 8
// 13
// 21
// 34

このジェネレータは、有名な数列であるフィボナッチ数列を生成します。前の二つの数の和が次の数である数列です。これは、前の二つのステップから次のステップを築く終わりなき階段のようです!

そして、ここまで、私たちのプログラミングの弟子たちは、イテレータとジェネレータの土地を旅し、その類似点と違いを見て、自分たちで魔法を創りました。実践が完璧を生むことを忘れないでください。これらの概念を試してみてください。あなたが何か素晴らしいプログラムを作成するかもしれません。幸せなプログラミングをし、あなたのコードが常に最初の試行でコンパイルされることを祈っています!

Credits: Image by storyset