Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

javascript で遊ぶラムダ式、クロージャ、カリー化

javascript で遊ぶラムダ式、クロージャ、カリー化
by

rti 7743

on 5 September 2011

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of javascript で遊ぶラムダ式、クロージャ、カリー化

javascript で遊ぶ
ラムダ式、クロージャ、カリー化 by rti. ソートの比較関数 Array.sort(比較関数) //比較関数
function compare(a,b)
{
return (b - a):
}
//ソートする
Array.sort(compare) 逆にしたいなー
function compare(a,b)
{
// return (b - a):
return (a - b):
}
Array.sort(compare) ソートするときの
比較用の関数を別に定義できる。
アウトソースできる。 これで何が嬉しいか? 汎用性の確保 逆にするのも楽だし。
function compare(a,b)
{
// return (b - a):
return (a - b):
}
Array.sort(compare) 確かにコレは便利なんだけど、
だけど比較関数を
いちいち定義するのが
メンドイ。 //比較関数
function compare(a,b)
{
return (b - a):
}

//ソート実行
Array.sort(compare) 何で毎回
定義しないとダメなの? compareって
使い捨ての関数ぢゃないですか。
ソートでしか使わないし、、、 λ そこで
無名関数(ラムダ式)ですよ。 ハーフライフではなく、
ラムダです。 function compare(a,b)
{
return (b - a):
}
Array.sort(compare) Array.sort(
function(a,b)
{
return (b - a):
}
); 関数ですが、名前がありません。
いわば「ななしさん」状態です。
こーゆー関数を無名関数と呼びます。 Array.sort(
function(a,b)
{
return (b - a):
}
); 利点:
使う場面で
簡単に定義できること。 Array.sort(
function(a,b)
{
return (b - a):
}
); 無名関数 //変数に代入もできます。
var func = function(a,b){ return (b - a): };

//変数から呼び出せます。
alert( func(1,2) ); // 2 - 1 で 1 が表示される。

//return で戻り値として返せます。
return func; 無名関数は、
変数に代入したり、
戻り値に返せたりします。 return の戻り値で関数が返せる
ということは、
こういうことができますね。 関数を返す関数
function make_compare()
{
return function(a,b)
{
return (b - a):
};
}

//関数を受け取る
var func = make_compare();
//実行
// 2 - 1 で 1 が表示される。
alert( func(1,2) ); さて、
先ほどの比較関数を応用して、
文字列比較を行いましょう。 文字列の比較を行う。
function make_compare()
{
return function(a,b)
{
if (b == a)
{
return 0;
}
else if (b < a)
{
return -1;
}
else
{
return 1; //b > a
}
};
}

var func = make_compare();

//"zar" > "jpy" で1が帰ってくる。
alert( func("jpy","zar") ); jpy(円) 日本円
zar(ざー) 南アフリカランド 要求! :
先頭の 2文字で比較してほしい。 //z「a」r < j「p」y で比較するので、
// -1 が帰ってくる。
alert( func("jpy","zar") ); 問題は、
2文字目だということを
比較関数にどう伝えるか。 function make_compare()
{
return function(a,b)
{
//とりあえずどコーディング
var aa = a[1] || ""; //短い文字は ""
var bb = b[1] || "";

if (bb == aa)
{
return 0;
}
else if (bb < aa)
{
return -1;
}
else
{
return 1; //bb > aa
}
};
}

var func = make_compare();

//z「a」r < j「p」y で比較するので、 -1 が帰ってくる。
alert( func("jpy","zar") ); とりあえず、
2文字目で
ハードコーディング
してみよう。 なんかいけていない。
もっと一般化できないの? N文字目でソートとか
できないの? できるよ、
そう、クロージャならね。 n文字目で比較する関数を返す関数
function make_compare(n)
{
return function(a,b)
{
//n文字目で比較
var aa = a[n] || "";
var bb = b[n] || "";

if (bb == aa)
{
return 0;
}
else if (bb < aa)
{
return -1;
}
else
{
return 1; //bb > aa
}
};
}

var func = make_compare(1);

//z「a」r < j「p」y で比較するので、 -1 が帰ってくる。
alert( func("jpy","zar") ); あれ!?
(つд⊂)ゴシゴシ n のスコープってどこ?
(;゚ Д゚) …!? n文字目で比較する関数を返す関数
function make_compare(n)
{
return function(a,b)
{
//n文字目で比較
var aa = a[n] || "";
var bb = b[n] || "";

if (bb == aa)
{
return 0;
}
else if (bb < aa)
{
return -1;
}
else
{
return 1; //bb > aa
}
};
}

var func = make_compare(1);

//z「a」r < j「p」y で比較するので、 -1 が帰ってくる。
alert( func("jpy","zar") ); 引数のN ここでも有効 return したときにも
n は消えていない。 この状態を
「変数 n が
関数に束縛(bind/capture)
されている。」

とかいいます。 もう一度よく眺める。 n文字目で比較する関数を返す関数
function make_compare(n)
{
return function(a,b)
{
//n文字目で比較
var aa = a[n] || "";
var bb = b[n] || "";

if (bb == aa)
{
return 0;
}
else if (bb < aa)
{
return -1;
}
else
{
return 1; //bb > aa
}
};
}

var func = make_compare(1);

//z「a」r < j「p」y で比較するので、 -1 が帰ってくる。
alert( func("jpy","zar") ); 変数 n を束縛(bind)している こんなふうに関数を返す関数の中で、
変数を束縛(bind/capture)するものを
クロージャと呼びます。 n文字目で比較する関数を返す関数
function make_compare(n)
{
return function(a,b)
{
//n文字目で比較
var aa = a[n] || "";
var bb = b[n] || "";

if (bb == aa)
{
return 0;
}
else if (bb < aa)
{
return -1;
}
else
{
return 1; //bb > aa
}
};
}

var func = make_compare(1);

//z「a」r < j「p」y で比較するので、 -1 が帰ってくる。
alert( func("jpy","zar") ); クロージャ ちなみに、
参照だけではなく、
書き込みも可能です。 呼び出すたびに
カウントアップしていく関数を作成する
function make_countup(first)
{
var c = first;
return function()
{
c += 1;
return c;
};
}

//最初は10
var func = make_countup(10);
alert( func() ); //10 + 1 で 11
alert( func() ); //11 + 1 で 12
alert( func() ); //12 + 1 で 13 これがクロージャ。 この娘はクローディア ここまでのまとめ。 ・無名関数とは
使い捨ての名前のない関数

・関数を返す関数
その名の通り、
関数を戻り値で返す関数。

・クロージャ
関数を返す関数の中で、
変数を束縛(bind/capture)
する関数。 //ソースコードで説明
function make_countup(first)
{
var c = first;
return function()
{
c += 1;
return c;
};
}

//最初は10
var func = make_countup(10);
alert( func() ); //10 + 1 で 11
alert( func() ); //11 + 1 で 12
alert( func() ); //12 + 1 で 13 クロージャ クロージャと関数を返す関数の違い 変数を束縛するか
しないかの違い。 クロージャと関数を返す関数の違い //ただの関数を返す関数
function make_add()
{
return function()
{
return a + b;
};
}


//クロージャを返す関数
function make_add()
{
var n = 10;
return function()
{
return a + b + n;
};
} nを束縛するので
クロージャ まとめ終わり。 クロージャはすごい。←結論 クロージャを利用した
面白い例として、
関数の引数を
少なくすることが出来ます。 直前にならないと
決まらない値以外を

事前に設定できないか? javascript では無理なんだけど、
配列リストから検索する関数を
考えます。


//検索する
ArraySearch
(検索するもの,検索されるもの,オプション) ; おまけ
いろんな言語のクロージャ モダンな言語には、
たいていクロージャが実装されています。 いきなりですが、
ソートの比較関数をご存知ですか? キリッ 関数の部分適応とカリー化 オプションは予め決まっている。
検索するものと、
検索されるものは、
使用する直前まで定まらない ArraySearch(検索するもの,検索されるもの,オプション); 検索するものと、
検索されるものは、
直前になるまで決まらない。 オプションは
事前に決まる、 オプションだけを固定化してみる(関数の部分適応) function transArraySearch(オプション)
{
return
function(検索するもの,検索されるもの)
{
return ArraySearch
(検索するもの,検索されるもの,オプション)
};
} //フルで呼び出す.
ArraySearch(検索するもの,検索されるもの,オプション)


//関数の部分適応をやってみる.
var newArraySearch = transArraySearch(MY_OPTION);

~なにか処理~

newArraySearch(検索するもの,検索されるもの); //オプションが消えた. function transArraySearch(オプション)
{
return
function(検索するもの,検索されるもの)
{
return ArraySearch
(検索するもの,検索されるもの,オプション)
};
} 引数をより簡略化した関数を
動的に作成することができました。 これとは何が違うの? function ArraySearch2
(検索するもの,検索されるもの)
{
return
ArraySearch(検索するもの,
検索されるもの,
オプション決め打ち);
} これだと、オプションが決め打ちになってしまい、
あとで別のオプションに変更することができない。 このようにクロージャ等を利用して関数

の引数の数の少ない関数を作ることを 「関数の部分適用」 と呼びます。 また、「関数の部分適用」の中でも、
関数の引数をひとつだけにする行為を 「カリー化」 と呼びます。 検索されるものとオプションを固定化して1パラメータにしてみる(カリー化) ArraySearch(検索するもの,検索されるもの,オプション); 直前になるまで
決まらない 事前に決まる 検索するものは 検索内容は、 ・C++ (C++0x以上)
int cap = 1;
auto f = [cap](int x) ->
int { return x + 1 + cap; };
int i = f(70); //72



・C# (3.0以上)
int cap = 1;
Func<int, int> f = x => x + 1 + cap;
int i = f(70); //72



・PHP (5.3以上)
$cap = 1;
$f = function($x) use($cap)
{
return $x + 1 + $cap;
};
$i = $f(70); //72



・java(次期バージョン)
int cap = 1;
#int(int) f = #(x)(x + 1 + cap);
int i = f.(70); //72 参考文献 JavaScriptでカリー化 / 檜山正幸のキマイラ飼育記
http://d.hatena.ne.jp/m-hiyama/20051213/1134446855

猿でもわかるクロージャ超入門 / DQNEO起業日記
http://dqn.sakusakutto.jp/2009/01/javascript.html

http://favotter.net/status.php?id=15562586819
http://favotter.net/status.php?id=15563705748
http://favotter.net/status.php?id=15562979662

いろんな言語のラムダ式とキャプチャ
http://d.hatena.ne.jp/rti7743/20100611/1276289872

ただのクロージャとカリー化の違いがよくわからない
http://d.hatena.ne.jp/rti7743/20100505/1273011836

http://twitter.com/#!/kinaba/status/15562586819 このスライドの誤りはrtiの責任であり、
参考文献の責任ではありません。 えんいー 検索されるものとオプションを固定化して1パラメータにしてみる(カリー化) function curryArraySearch(検索されるもの,オプション)
{
return function(検索するもの)
{
return
ArraySearch(検索するもの,検索されるもの,オプション)
};
}

var f = curryArraySearch(検索されるもの,MY_OPTION);
f(検索するもの); 引数が1パラメータの関数を動的につくることができました。
この行為をカリー化といいます。 カリー化についての疑問あれこれ 残すパラメータは最初のパラメータでなければいけない?
--> No. 第二引数とかを残してもいいらしい。
ただ、大抵のカリー化は最初の引数を残している。 ArraySearch(検索するもの,検索されるもの,オプション)

curreyArraySearch(検索するもの) //これでもOK
ArraySearch(検索するもの,検索されるもの,オプション)

curreyArraySearch(検索されるもの) //これはダメ. 2引数なので関数の部分適応
ArraySearch(検索するもの,検索されるもの,オプション)

curreyArraySearch(検索するもの,検索されるもの) まとめ クロージャを利用し、関数の部分適応を利用すると、
引数を少なくした関数を動的に作成することができます。
この引数の数の少ない関数を作ることを関数の部分適用といい
ます。 ArraySearch(検索するもの,検索されるもの,オプション)

newArraySearch(検索するもの,検索されるもの) 関数の部分適応の中で、
関数の引数を1引数にすることをカリー化といいます。 ArraySearch(検索するもの,検索されるもの,オプション)

curreyArraySearch(検索するもの)
Full transcript