1. カレーとは何か数学とコンピュータ サイエンスにおいて、カリー化とは、複数の引数を取る関数を、単一の引数を取る一連の関数に変換する手法です。 たとえば、3 つのパラメータを取る通常の関数の場合、カリー化後、カリー化されたバージョンの関数は 1 つのパラメータを取り、次のパラメータを取る関数を返します。この関数は 3 番目のパラメータを取る関数を返します。 最後の関数は、3 番目のパラメータを受け取った後、以前に受け取った 3 つのパラメータを元の通常の関数に適用し、最終結果を返します。 数学と計算科学におけるカリー化: // 数学と計算科学におけるカリー化: //3つのパラメータを受け取る通常の関数 function sum(a,b,c) { コンソールログ(a+b+c) } //通常の関数をカリー化されたバージョンに変換するために使用されるツール関数 function curry(fn) { //... 内部実装は省略され、新しい関数が返されます } //カリー化された関数を取得します。let _sum = curry(sum); // 2番目のパラメータを受け取る関数を返します。let A = _sum(1); //3番目のパラメータを受け取る関数を返します。let B = A(2); //最後のパラメータを受け取り、以前のすべてのパラメータを元の関数に適用し、B(3)を実行します // print : 6
数学とコンピュータ サイエンスでは、カリー化された関数には一度に 1 つの引数しか渡すことができません。 実際の 次の例を見てみましょう。 //通常の関数 function fn(a,b,c,d,e) { コンソールログ(a,b,c,d,e) } //生成されたカリー関数 let _fn = curry(fn); _fn(1,2,3,4,5); // 出力: 1,2,3,4,5 _fn(1)(2)(3,4,5); // 出力: 1,2,3,4,5 _fn(1,2)(3,4)(5); // 出力: 1,2,3,4,5 _fn(1)(2)(3)(4)(5); // 印刷: 1,2,3,4,5 カリー化された カリー化とは何かがわかったところで、カリー化が何のために使用されるのかを見てみましょう。 2. カレーの用途カリー化は実際には単純な答えを複雑にしますが、同時に関数を使用する際の自由度が高まります。 ここでの関数パラメータの自由な処理がカリー化の核心です。 カリー化の本質は、一般性を減らして適用性を高めることです。例を見てみましょう: 私たちの仕事では、電話番号、メールアドレス、ID番号、パスワードなどの検証など、正規表現の検証を必要とするさまざまな要件に遭遇します。このとき、検証する正規表現オブジェクトと検証する文字列の 2 つのパラメータを受け取る一般的な関数 関数 checkByRegExp(regExp,文字列) { regExp.test(文字列)を返します。 } checkByRegExp(/^1\d{10}$/, '18642838455'); // 電話番号をチェック checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, '[email protected]'); // メールアドレスをチェック 一見すると、上記のコードは問題なく、正規表現テストに合格するためのすべてのニーズを満たすことができます。 しかし、次の質問を考えてみましょう。複数の電話番号や複数のメールアドレスを確認する必要がある場合はどうなるでしょうか? 次のようにするかもしれません: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : チェックを行うたびに正規表現の文字列を入力する必要があります。同じ種類のデータをチェックする場合、同じ正規表現を複数回記述する必要があり、使用時に非効率的です。また、 この時点で、カリー化を使用して //カリー化を実行します。let _check = curry(checkByRegExp); //電話番号を確認するツール関数を生成します。let checkCellPhone = _check(/^1\d{10}$/); //メールレットを検証するためのツール関数を生成します。checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/); checkCellPhone('18642838455'); // 電話番号を確認checkCellPhone('13109840560'); // 電話番号を確認checkCellPhone('13204061212'); // 電話番号を確認checkEmail('[email protected]'); // メールを確認checkEmail('[email protected]'); // メールを確認checkEmail('[email protected]'); // メールを確認 カプセル化をカリー化した後、コードが簡潔で直感的になるかどうかを確認してみましょう。 カリー化後、 別の例を見てみましょう 次のようなデータがあるとします。 リスト = [ { 名前: 'ルーシー' }, { 名前: 'ジャック' } ] データ内のすべての名前属性の値を取得する必要があります。通常は次のようにします。 名前をリスト.map(function(item) { item.name を返します。 }) では、これをカリー化された思考でどのように実装するのでしょうか? prop = curry(function(key,obj) { obj[キー]を返します。 }) 名前をリスト.map(prop('name'))とします。 これを見て、疑問に思うかもしれません。 考え方を変えると、 実際のコードは つまり、カリー化によって、コードはより簡潔になり、読みやすくなりました。 3. カリー化ユーティリティ関数をカプセル化する方法次に、 以前のカリー化の定義を思い出してください。カリー化では、いくつかのパラメータを受け取り、残りのパラメータを受け取る関数を返し、十分なパラメータを受け取った後に元の関数を実行します。 カリー化された関数が十分なパラメータを受け取ると元の関数が実行されることは既にわかっていますが、十分なパラメータに達したかどうかをどのように判断するのでしょうか? 私たちには 2 つのアプローチがあります:
これら 2 つのポイントを組み合わせて、単純な /** * 関数をカリー化します * @param fn カリー化される元の関数 * @param len 必要なパラメータの数。デフォルトは元の関数の仮パラメータの数です */ 関数curry(fn,len = fn.length) { _curry.call(this,fn,len) を返します } /** * 転送関数 * @param fn カリー化される元の関数 * @param len 必要なパラメータ数 * @param args 受信したパラメータリスト */ 関数_curry(fn,len,...args) { 関数を返す (...パラメータ) { _args = [...args,...params] とします。 if(_args.length >= len){ fn.apply(this,_args) を返します。 }それ以外{ _curry.call(this,fn,len,..._args) を返します。 } } } これを検証してみましょう: _fn = curry(function(a,b,c,d,e){ コンソールログ(a,b,c,d,e) }); _fn(1,2,3,4,5); // 出力: 1,2,3,4,5 _fn(1)(2)(3,4,5); // 出力: 1,2,3,4,5 _fn(1,2)(3,4)(5); // 出力: 1,2,3,4,5 _fn(1)(2)(3)(4)(5); // 印刷: 1,2,3,4,5 よく使用されるツール ライブラリ たとえば、プレースホルダーを渡すと、この呼び出しで渡されるパラメーターはプレースホルダーをスキップし、プレースホルダーには次の呼び出しのパラメーターが次のように入力されます。 公式サイトの例を見てみましょう。 次にプレースホルダー機能の実装方法を考えてみましょう。 私たちが独自に実装した プレースホルダを使用する目的は、パラメータを渡す順序を変更することです。そのため、 コード上で直接: /** * @param fn カリー化される関数* @param length 必要なパラメータの数。デフォルトは関数の仮パラメータの数* @param holder プレースホルダ。デフォルトは現在のカリー化関数* @return {Function} カリー化後の関数*/ 関数 curry(fn,length = fn.length,holder = curry){ _curry.call(this,fn,length,holder,[],[]) を返します } /** * 転送関数* @param fn カリー化の元の関数* @param length 元の関数に必要なパラメータの数* @param holder 受け取ったプレースホルダ* @param args 受け取ったパラメータリスト* @param holders 受け取ったプレースホルダの位置リスト* @return {Function} カリー化を続行する関数または最終結果*/ 関数 _curry(fn,長さ,ホルダー,引数,ホルダー){ 関数(..._args)を返す{ // 同じ関数に対する複数の操作による混乱を避けるためにパラメータをコピーします。let params = args.slice(); //プレースホルダーの位置リストをコピーし、新しく追加されたプレースホルダーをここに追加します。let _holders = holders.slice(); //パラメータをループし、パラメータを追加したり、placeholders_args.forEach((arg,i)=>{ //実パラメータの前にプレースホルダーがあります。プレースホルダーを実パラメータに置き換えます。if (arg !== holder && holders.length) { index = holders.shift() とします。 _holders.splice(_holders.indexOf(インデックス),1); パラメータ[インデックス] = 引数; } //実際のパラメータの前にプレースホルダはありません。パラメータをパラメータリストに追加します。else if (arg !== holder && !holders.length) { パラメータをプッシュします。 } //プレースホルダーが渡されます。前にプレースホルダーがない場合は、プレースホルダーの位置を記録します。else if (arg === holder && !holders.length) { パラメータをプッシュします。 _holders.push(params.length - 1); } //渡されたプレースホルダーの前にプレースホルダーがある場合は、元のプレースホルダーの位置を削除します。そうでない場合は、(arg === holder && holders.length) { ホルダー.shift(); } }); // params の最初の length レコードにはプレースホルダーが含まれていないので、関数 if(params.length >= length && params.slice(0,length).every(i=>i!==holder)){ を実行します。 fn.apply(this,params); を返します。 }それ以外{ _curry.call(this,fn,length,holder,params,_holders) を返します。 } } } 確認します: fn = 関数(a, b, c, d, e) { コンソールにログ出力します。 } let _ = {}; // プレースホルダーを定義 let _fn = curry(fn,5,_); // 関数をカリー化し、必要なパラメーターの数を指定し、必要なプレースホルダーを指定します _fn(1, 2, 3, 4, 5); // print: 1,2,3,4,5 _fn(_, 2, 3, 4, 5)(1); // 出力: 1,2,3,4,5 _fn(1, _, 3, 4, 5)(2); // 出力: 1,2,3,4,5 _fn(1, _, 3)(_, 4,_)(2)(5); // 出力: 1,2,3,4,5 _fn(1, _, _, 4)(_, 3)(2)(5); // 出力: 1,2,3,4,5 _fn(_, 2)(_, _, 4)(1)(3)(5); // 出力: 1,2,3,4,5 カレー機能を本格的に実装しました〜〜 フロントエンド JavaScript の関数カリー化を徹底的に理解する方法に関するこの記事はこれで終わりです。JavaScript 関数カリー化の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Ubuntu16.04にclionをインストールするプロセス全体と手順の詳細な説明
>>: MySQLで最新のトランザクションIDを照会する方法
1. ダウンロード: http://www.oracle.com/technetwork/java/...
XHTML には多くのタグがありますが、頻繁に使用されるのはごくわずかであり、習得する必要があるのは...
目次ブラウザ同一生成元ポリシー1. VUEフロントエンド構成プロキシはクロスドメインの問題を解決しま...
序文この記事では主にMySQLでトランザクションを開始する方法について紹介します。関連情報については...
Compose のいくつかの部分は、何らかの方法で環境変数を扱います。このチュートリアルは、必要な情...
この記事では、Echartsを使用して3次元棒グラフを実装するVueの具体的なコードを参考までに共有...
目次導入実装手順キャンバス環境を作成するライティングボールBallクラスを継承するMoveBallク...
問題の背景業務システムのサーバ監視システムからディスク使用率が90%に達したという早期警告通知が来た...
目次テーブルの目的例えばテーブル分割戦略すでにオンラインになっている実行中のテーブルはどうすればよい...
目次序文非同期読み込みパッケージコンポーネントコンポーネントの使用インターフェースをカスタマイズする...
この記事では、フォーム検証を実装するためのVueの具体的なコードを例として紹介します。具体的な内容は...
今日ログインページを書いていたとき、個人情報と携帯電話番号を認証する必要がありましたが、ページにボタ...
この記事を書いた理由は、修正した分散 PyTorch プログラムを Facebook のクラスター上...
この記事の例では、メモ帳機能を実装するためのVueの具体的なコードを参考までに共有しています。具体的...
1. 背景インターネット アプリケーションの急速な更新と反復という状況では、従来の手作業や単純なスク...