概要プログラミング言語理論において、遅延評価(英語: Lazy Evaluation)は、遅延計算、遅延評価とも呼ばれ、必要に応じて呼び出すとも呼ばれ、コンピュータプログラミングの概念です。その目的は、コンピュータが行う作業を最小限に抑えることです。これには、「遅延評価」と「最小化された評価」という、関連性はあるものの異なる 2 つの意味があります。パフォーマンスの向上に加えて、遅延評価の最も重要な利点は、無限のデータ型を構築できることです。 関数型言語での遅延評価を見て、遅延評価の理解を深めるために JavaScript で最もシンプルな実装を書いてみたいと思いました。 2 つのメソッドが使用され、どちらも基本的な配列の遅延評価を実装するのに 80 行未満しかかかりません。 達成方法遅延評価では、評価されるたびに値を返すのではなく、計算パラメータを含む評価関数を返します。計算は、値が使用されるたびに実行されます。 遅延操作が複数ある場合、評価関数のチェーンが形成されます。評価が実行されるたびに、各評価関数は前の評価関数を評価し、値を返します。最後に、計算関数が終了すると、終了値が返されます。 具体的な実装評価関数の終了を決定する関数の各評価ではさまざまなデータが返されるため、フローが完了したかどうかを判断するためのマーカーとして一意の値を使用する必要があります。たまたま、Symbol() は、他のどの値とも等しくない値を持つ新しいシンボルを作成できます。 const over = シンボル(); 定数isOver = 関数(_over) { _over === over を返します。 } 生成関数の範囲範囲関数は、開始パラメータと終了パラメータを受け入れ、評価関数を返し、評価関数を実行して値を返し、終了時に終了値を返します。 const範囲 = 関数 (から、まで) { i = からとします。 関数を返す(){ もし(i < to){ 私は++ console.log('範囲\t', i); 戻る } 戻る; } } 変換関数マップ評価関数と処理関数を受け入れ、評価関数フローでデータを取得し、データを処理してフローを返します。 const map = 関数 (フロー、変換) { 関数を返す(){ 定数データ = フロー(); console.log('map\t', データ); isOver(data) を返します ? data : transform(data); } } フィルター評価関数を受け入れ、評価関数フロー内のデータをフィルタリングし、一致するデータを検索して返します。 const filter = 関数 (フロー、条件) { 関数を返す(){ while(true) { 定数データ = フロー(); if (isOver(データ)) { データを返します。 } if(条件(データ)) { console.log('filter\t', データ); データを返します。 } } } } 割り込み機能停止評価関数を受け入れ、特定の条件に達したときに中断します。クロージャ関数と停止関数を使用してから、テイク関数を実装できます。 const stop = 関数 (フロー、条件) { _stop = false とします。 関数を返す(){ if (_stop) は戻ります; 定数データ = フロー(); if (isOver(データ)) { データを返します。 } _stop = 条件(データ); データを返します。 } } const take = function(flow, num) { i = 0 とします。 戻り値 stop(flow, (data) => { ++i >= num を返します。 }); } コレクション関数結合返されるものはすべて関数なので、最後に join 関数を使用してすべての値を収集し、配列を返す必要があります。 const join = 関数 (フロー) { 定数配列 = []; while(true) { 定数データ = フロー(); if (isOver(データ)) { 壊す; } 配列.push(データ); } 配列を返します。 } テスト:const nums = join(take(filter(map(range(0, 20), n => n * 10), n => n % 3 === 0), 2)); console.log(数値); 出力:
よりエレガントな実装遅延評価は上記の関数 + クロージャを使用して実装されていますが、まだ十分にエレガントではありません。コードの大部分は反復処理と評価が完了したかどうかの判断に費やされています。実際、es6 で遅延評価を実現するには、ジェネレータを使用するというより良い方法があります。ジェネレータは、反復処理を解決し、フローが完了したかどうかを判断するのに役立ちます。ロジックに集中して、より簡潔で理解しやすく、明確に構造化されたコードを書くことができます。 const範囲 = 関数* (から、まで) { for(i = from; i < to; i++) { console.log('範囲\t', i); 利回り i; } } const map = function* (flow, transform) { for(フローのconstデータ) { console.log('map\t', データ); yield(変換(データ)); } } const filter = function* (フロー, 条件) { for(フローのconstデータ) { console.log('filter\t', データ); if (条件(データ)) { 収量データ; } } } const stop = function*(flow, condition) { for(フローのconstデータ) { 収量データ; if (条件(データ)) { 壊す; } } } const take = 関数 (フロー、数値) { count = 0 とします。 const _filter = 関数 (データ) { カウント++ count >= 数値を返します。 } stop(flow, _filter) を返します。 } チェーン呼び出しを追加することで完了します。 クラス _Lazy{ コンストラクタ() { this.iterator = null; } 範囲(...引数) { this.iterator = range(...args); これを返します。 } マップ(...引数) { this.iterator = map(this.iterator, ...args); これを返します。 } フィルター(...引数) { this.iterator = フィルター(this.iterator, ... 引数); これを返します。 } (...引数)を取る{ this.iterator = take(this.iterator, ...args); これを返します。 } [シンボル.イテレータ]() { this.iterator を返します。 } } 関数遅延(){ 新しい_Lazy() を返します。 } 最後に、もう一度テストします。 const nums = lazy().range(0, 100).map(n => n * 10).filter(n => n % 3 === 0).take(2); for(let n of nums) { console.log('num:\t', n, '\n'); } 出力:
はい、完了しました。 要約するこのようにして、最も単純な配列遅延評価ライブラリが完成しました。ここでは、遅延評価を単純に実装するだけです。プロジェクトに組み込むには、多くの詳細を追加する必要があります。コードはわずか 80 行なので、遅延評価の原理を明確に理解し、ジェネレーターの理解を深めることができます。 上記は、JavaScript で配列遅延評価ライブラリを実装する方法の詳細です。JavaScript で配列遅延評価ライブラリを実装する方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: mysqld_multi を使用して単一のマシンに複数のインスタンスをデプロイする方法に関する MySQL チュートリアル
導入MySQL は、私たちが日常業務で使用する非常に一般的なデータベースです。MySQL は現在 O...
今日、データベース操作はますますアプリケーション全体のパフォーマンスのボトルネックになりつつあり、こ...
目次序文配列.isArrayコンストラクタインスタンスプロトタイプオブジェクト.プロトタイプ.toS...
この記事では、jQuery Canvasの描画画像検証コードの具体的なコードを例として紹介します。具...
質問Nginx リバース プロキシの後、Tomcat アプリケーションは、クライアント ブラウザーの...
Nginx を使用して Tomcat9 クラスターを構築し、Redis を使用してセッション共有を実...
背景プロジェクト開発プロセスでは、前のページから次のページにジャンプする必要に迫られることがよくあり...
私たちのベテランの先人たちは、数え切れないほどのコードを書き、数え切れないほどの落とし穴に陥ってきま...
目次1. 理論シリアル化可能繰り返し読み取りコミットされた読み取りコミットされていない読み取り2. ...
以前、プロジェクトを開発しているときに、flex レイアウトと position:absolute/...
Docker コンテナ間の相互接続と通信には 3 つの方法があります。 Docker 内部ネットワー...
目次1. jsメモリ2. 譲渡3. 浅いコピー4. ディープコピー序文:以下の記事を読む前に、記憶に...
目次ドキュメント オブジェクト モデル (DOM) DOM と JavaScript DOMツリーの...
目次開発環境ゲームエンジンのコンセプトCocos Creatorについてプロジェクト構造コード編集環...
エフェクト表示: 環境準備コントローラーノード: 6GB 4時間60GB/30GB/30GB計算ノー...