私の限られた理解は次のとおりです:
1)部分関数アプリケーション
部分関数アプリケーションは、引数の数が少ない関数を返すプロセスです。3つの引数のうち2つを指定すると、3-2 = 1の引数を取る関数が返されます。3つの引数のうち1つを指定すると、3-1 = 2引数を取る関数が返されます。必要に応じて、3つの引数のうち3つを部分的に適用することもでき、引数をとらない関数を返します。
したがって、次の関数が与えられます:
f(x,y,z) = x + y + z;
1をxにバインドし、それを上記の関数に部分的に適用すると、次のようにf(x,y,z)
なります:
f(1,y,z) = f'(y,z);
どこ: f'(y,z) = 1 + y + z;
yを2にバインドし、zを3にバインドし、部分的に適用f'(y,z)
すると、次のようになります。
f'(2,3) = f''();
どこに:f''() = 1 + 2 + 3
;
これで、任意の時点でf
、f'
またはの評価を選択できますf''
。だから私はできる:
print(f''()) // and it would return 6;
または
print(f'(1,1)) // and it would return 3;
2)カレー
一方、カリー化は、関数を1つの引数関数のネストされたチェーンに分割するプロセスです。2つ以上の引数を指定することはできません。1つまたは0です。
したがって、同じ関数を与えられます:
f(x,y,z) = x + y + z;
カリー化すると、3つの関数のチェーンが得られます。
f'(x) -> f''(y) -> f'''(z)
どこ:
f'(x) = x + f''(y);
f''(y) = y + f'''(z);
f'''(z) = z;
お電話の場合は今すぐf'(x)
にx = 1
:
f'(1) = 1 + f''(y);
新しい関数が返されます:
g(y) = 1 + f''(y);
あなたが呼び出す場合g(y)
にy = 2
:
g(2) = 1 + 2 + f'''(z);
新しい関数が返されます:
h(z) = 1 + 2 + f'''(z);
最後に、あなたが呼び出す場合h(z)
にz = 3
:
h(3) = 1 + 2 + 3;
あなたが返され6
ます。
3)閉鎖
最後に、クロージャーとは、関数とデータを単一のユニットとして一緒に取り込むプロセスです。関数クロージャは、0から無限の数の引数を取ることができますが、渡されないデータも認識します。
繰り返しますが、同じ関数が与えられた場合:
f(x,y,z) = x + y + z;
代わりにクロージャーを書くことができます:
f(x) = x + f'(y, z);
どこ:
f'(y,z) = x + y + z;
f'
が閉鎖されていx
ます。f'
内部にあるxの値を読み取ることができるという意味f
。
だからあなたが電話f
する場合x = 1
:
f(1) = 1 + f'(y, z);
あなたは閉鎖を得ます:
closureOfF(y, z) =
var x = 1;
f'(y, z);
ここclosureOfF
でy = 2
andで呼び出した場合z = 3
:
closureOfF(2, 3) =
var x = 1;
x + 2 + 3;
どちらが返されます 6
結論
カリー化、部分適用、およびクロージャーはすべて、機能をより多くの部分に分解するという点で多少似ています。
カリー化は、複数の引数の関数を、単一の引数の関数を返す単一の引数のネストされた関数に分解します。1つ以下の引数の関数をカリー化しても意味がありません。
部分的なアプリケーションは、複数の引数の関数をより小さな引数の関数に分解し、現在欠落している引数が指定された値に置き換えられます。
クロージャーは、関数を関数とデータセットに分解し、関数内の渡されなかった変数がデータセット内を調べて、評価を求められたときにバインドする値を見つけることができます。
これらすべてについて混乱しているのは、他のサブセットを実装するためにそれぞれを使用できることです。そのため、本質的に、それらはすべて実装の詳細のビットです。すべての値を事前に収集する必要がなく、関数の一部を個別の単位に分解しているため、関数の一部を再利用できるという点で、これらはすべて同じ値を提供します。
開示
私は決してこのトピックの専門家ではありません。最近これらのことを学び始めたばかりなので、現在の理解を提供しますが、間違いがあるかもしれませんので、指摘するように勧めます。発見します。