今、突然思いつきました。次のステップに進んでイテレータを直接走査することはほとんどないのに、なぜこの次のステップを実装する必要があるのでしょうか?それぞれをこのように、このように順番に直接実装します。はい、すべてを理解できます。すぐに最初の超簡潔なバージョンを書きました。
function yieldHost(yieldFunction)
{
return function (processer)
{
var yield = function (result) )
{
processer(result)
};
yieldFunction(yield)
}
アイデアを変更した後のコード本当に簡潔です。
最初に例を添付してから、原則について話します。
まず、次のような列挙する関数が必要です:
関数 fun(yield)
{
for (var i = 0; i yield(i)
}
または次のようにします:
function fun( yield)
{
yield(1);
yield(2)
}
C# とは実装が異なるためしたがって、ループ内では、本体内に yield Break や yield continue のような構文は必要なく、単に Break または continue だけです。
実際のアプリケーションでは、yieldHost 関数は、要件を満たす上記の fun 関数を列挙子に変換できます。
var enumerator = yieldHost(fun);
この列挙子は、jQuery の各関数と同様に、実際には関数です。 、列挙を処理するハンドラー関数を受け取ります:
enumerator(function (item)
{
window.alert(item);
});
原理について話しましょう。
従来の列挙子の場合、呼び出されるたびに列挙子が値を返す必要があると考えますが、Chen Zihan 氏が述べたように、これは実現できますが、関数を停止する必要があります。本当に面倒です。
しかし!実際、ほとんどの場合、列挙子にアクセスするには foreach などの構文を使用することがわかりました。これにより、次のメソッドを実装するのではなく、それぞれのメソッドを実装するという非常に簡単な方法が得られます。
それぞれの方法と次の方法の違いは何ですか? jQuery に詳しい人は、各メソッドが実際には列挙値を返す代わりに、関数を受け取り、列挙値をパラメータとして渡すものであることを知っているでしょう。
この動きにより、すべての問題は解決されました。関数の実行を一時停止する必要はなく、列挙値を処理するロジックをこの関数に挿入するだけで済みます。実際、ここでの yieldHost は反転作業を完了し、列挙子によって受け取られた関数 (つまり、window.alert(item)) を列挙関数 (つまり、fun) に挿入します。最終的な実行効果は次のようになります。
function fun(yield)
{
window.alert(1);
window.alert(2);
ということで、この非常に単純な実装が誕生しました。
この超簡単な実装で、次はjQueryの各メソッドのように、breakの場合はtrueを返し、Continueの場合はfalseを返す関数を実装するか、このような関数のみで無限集合を扱えるようになります。
正直に言うと、私の JavaScript の研究は完全ではありません。これは、yieldHost の 2 番目のバージョンです。
コードをコピーします
try
{
yieldFunction(function (result)
{
if (processer(result))
throw 例外;
} );
}
catch (e)
{
if (e !== 例外)
throw e;
}
これは明らかに完璧ではありませんが、これ以上のものは本当に思いつきません。
次のステップは、これに基づいて Select と Where を実装することです。これは実際には非常に簡単です。
function Select(列挙子、セレクター)
{
return function (fun)
{
列挙子(function (item )
{
return fun(selector(item));
})
}
}
これの修正方法は連続バージョンへの選択、つまり:
enumerator.Select( selector )(processor );
これは JavaScript にとってはそれほど難しいことではないと思います。 。 。 。
ただ、フレンドリーな構文を時期尚早に導入すると、JavaScript が非常に複雑で醜いものになってしまいます。だから、これはみんなに任せて遊んでもらいます。