Lambda演算子5 b:How of Y
Lambda演算子5 b:How of Y
実はこの文章の意訳です.節約したものがある.私物を少し増やした.次の投稿があります.
Yはかなり不思議ですが.その導きも完全に天外飛仙のように跡形もないわけではない.基本的に名前のない関数を自己参照できるようにするために,Yを一歩一歩抽象化した.だからYの導出過程が私たちのプログラマーにとってまだ意義があることを知っています:結局プログラミングの過程も抽象的な過程です.当時のボスたちがどのように複雑な表象から一般的な法則を抽象化したかを見てみると、私たちの今後の思考に大きなメリットがあるはずだ.ボスたちが実験できるようにJavaScriptを使いました.導出したプロセス全体はプログラミング時の再構成によく似ている.我々は大まかな解決策を提案し,それからよく観察し,抽象的な場所を見つけ,抽象的になる.より一般的な結果が得られた後,最適解が得られるまで再構成の手順を繰り返した.この投稿を見ている人は、小さなJavaScriptの使い方を知っているのではないでしょうか.それにブラウザがあればテスト環境があります.くだらないことは言わないで、コードを見てください.私たちはやはり階乗関数を例に挙げます.まず通常の書き方を見てみましょう.
1: function fact(n){
2: if(n == 0){
3: return 1;
4: }
5:
6: if(n > 0){
7: return n * fact(n - 1);
8: }
9: }
上のJavaScript関数は、内部呼び出し自体を定義します.この呼び出しが実行可能な前提は、関数名で関数定義を指すことです.つまり、
factという名前でバインドされた関数定義は上の関数体です.もし私たちが名前で関数を呼び出すことができなかったらどうしますか(lambda演算子と同じです).古い大会が「なぜこの制限を増やしたのか」と聞くかもしれない.自虐じゃないの?理由は簡単です:理論は物事の本質を探求する必要があります.オカムカミソリを覚えていますか?必要でない場合は、エンティティを追加しないでください.関数名は必須要素ですか、それとも文法糖ですか.この研究方法にも実際の意義がある:どんなに複雑なシステムでも簡単だが完備した基礎の上で構築された.強力なプログラミングツールは、常に積み重ねられた抽象に基づいており、最下位の抽象層は常に簡単です.簡単は透徹を意味し、簡単は丈夫を意味する.簡単は柔軟性を意味する.簡単は経済を意味する.問題は、いったいどこまで簡単なのかということです.どのようにシステムが役に立たないほど簡単ではないことを保証しますか?これは論理学者がシステムを構築する際にいつもシステムの正確性と完備性を証明しなければならない道理と同じである.Yを見つけると,元の関数名バインドは本質ではないことが分かった.
うん、続けます.関数#カンスウ#
factは再帰の基本形式である.関数内で直接関数名で別の関数を呼び出すことができない以上、少なくとも呼び出したい関数をパラメータで渡すことができます.そこで私たちは
fact2: 09: fact2 = function(himself, n){
10: return function(n){
11: if(n < 2){
12: return 1;
13: }
14:
15: return n * (something_expression_with_himself);
16: }
17: }
JavaScriptの匿名関数でlambda関数の名前のない特徴を強調します.ここではfact 2を使うのは純粋に便利です.変数fact 2自体は演算に関与していない.もし私たちがこのようにfact 2(fact 2,3)を呼び出すと、fact 2という関数は自分自身を呼び出すことができるのではないでしょうか.これは前に述べた自己引用のテクニックです:抽象を加えて、自分をパラメータを通じて自分に伝えます.私たちが解決しなければならないのはexpression_with_himeselfとは何ですか.fact 2もhimselfも自分を再帰的に呼び出さなければならないので、something_expression_with_himselfは直感的にhimself(himself,n−1)であるべきである.見たか?関数体と呼び出し方式は変わらないが,nはn−1になった.再帰と一致しましたね.19: fact3 = function(himself, n){
20: if( n < 2 ){
21: return 1;
22: }
23:
24: return n * himself(himself, n-1);
25: }
JavaScript consoleで試してみてください.fact 3(fact 3,3)は確かに6を返します.なに、JavaScript consoleないの?ボス、インターネットの銀はFireFoxを使わなくてもいいですか?FireFoxを使ったプログラマーはFireBugを使わなくてもいいですか?早くダウンロードしましょう.
ダウンロード完了?じゃ、続けましょう.lambda演算子の関数は1つのパラメータしか受け入れられていないのを覚えていますか?しかしfact 3は2つの関数を受け入れる.「カレー」を少し撒きます17: fact4 = function(himself){
18: return function(n){
19: if( n < 2 ){
20: return 1;
21: }
22:
23: return n * himself(himself)(n-1);
24: }
25: }
3を実行します.見てこそ信じられるよ.fact4(fact4)(3) = 6, fact4(fact4)(4) = 24, fact4(fact4)(5)=120....
今の問題は,この具体例の再帰方法を抽象化することである.自己引用とは関係のない細部を自己引用そのものと分ける必要があります.私たちが関心を持っているのは、自己誘導をどのように運用して再帰問題を解決するかだからです.himselfとnの分離に関するコードを先に解決することができる.これは,nを管理するコードが階乗を求めることにのみ関係しており,我々の関心の焦点ではないからである.例えば、フレームワークロジックとビジネスロジックを分離します.そこで関数fact 5を得た.37: fact5 = function(h){
38: return function(n){
39: var f = function(q){
40: return function(n){
41: if(n < 2){
42: return 1;
43: }
44:
45: return n * q(n-1);
46: }
47: }
48:
49: return f(h(h))(n);
50: }
51: }
いくつかの例を実行して自信を強めます:fact 5(fact 5)(3)=6、fact 5(fact 5)(4)=24..
注意関数fはfact 5に埋め込まれる必要はありません.次のように書くことができます37: fucntion f(q){
38: return function(n){
39: if(n < 2){
40: return 1;
41: }
42:
43: return n * q(n-1);
44: }
45: }
46:
47: function fact5(h){
48: return function(n){
49: return f(h(h))(n);
50: }
51: }
2つのことがわかります.1つは新しい関数です.
fはパラメータ化された階乗関数にすぎない――再帰部分がパラメータになる(関数でもある)
q了.第二に、fをさらに抽象化し、具体的な階乗部分を剥離することができ、Yを得た.69: function Y(f){
70: g = function(h){
71: return function(x){
72: return f(h(h))(x);
73: }
74: }
75:
76: return g(g);
77: }
Yを使用して階乗を実現できます.79: fact6 = Y(
80: function(h){
81: return function(n){
82: if(n < 2){
83: return 1;
84: }
85:
86: return n * h(n-1);
87: }
88: }
89: );
例えばfact 6(3)=6、fact 6(4)=24...
息が伸びる.4時間も書き続けて、やっとYについて書き終えた.以下では,より広範な組合せ演算子について述べることができる.主にS,K,Iの3つの演算子である.変態プログラミング言語unlambdaはSKIを解析して生計を立てている.
1: function fact(n){
2: if(n == 0){
3: return 1;
4: }
5:
6: if(n > 0){
7: return n * fact(n - 1);
8: }
9: }
09: fact2 = function(himself, n){
10: return function(n){
11: if(n < 2){
12: return 1;
13: }
14:
15: return n * (something_expression_with_himself);
16: }
17: }
19: fact3 = function(himself, n){
20: if( n < 2 ){
21: return 1;
22: }
23:
24: return n * himself(himself, n-1);
25: }
17: fact4 = function(himself){
18: return function(n){
19: if( n < 2 ){
20: return 1;
21: }
22:
23: return n * himself(himself)(n-1);
24: }
25: }
37: fact5 = function(h){
38: return function(n){
39: var f = function(q){
40: return function(n){
41: if(n < 2){
42: return 1;
43: }
44:
45: return n * q(n-1);
46: }
47: }
48:
49: return f(h(h))(n);
50: }
51: }
37: fucntion f(q){
38: return function(n){
39: if(n < 2){
40: return 1;
41: }
42:
43: return n * q(n-1);
44: }
45: }
46:
47: function fact5(h){
48: return function(n){
49: return f(h(h))(n);
50: }
51: }
69: function Y(f){
70: g = function(h){
71: return function(x){
72: return f(h(h))(x);
73: }
74: }
75:
76: return g(g);
77: }
79: fact6 = Y(
80: function(h){
81: return function(n){
82: if(n < 2){
83: return 1;
84: }
85:
86: return n * h(n-1);
87: }
88: }
89: );