再就職する前のワイ
ワイ「あー、今日は休みやな」
ワイ「いうて昨日も一昨日も休みやったけど」
娘(3歳)「パパ、お絵かきしよ」
ワイ「ええで」
娘「あれ描いて。あの・・・アンパンマ(n」
ワイ「おっとそこまでや」
ワイ「著作権のあるものを言うたらアカン」
ワイ「あれやな?アンパンパーソンのことやな?」
ワイ「描いたるで」
ワイ「チョイチョイチョイ、と」
ワイ「こうやな」
娘「わあ。上手。」
娘「次は食パンマ(n」
ワイ「食パンパーソンやな?」
ワイ「描いたる描いたる」
ワイ「チョイチョイチョイ、と」
ワイ「こうや」
ワイ「ついでにバイキンパーソンも描いたる」
娘「すごいね。上手だね。」
娘「じゃあ、次は・・・」
娘「カリー化された関数を書いて」
ワイ「(おっと?)」
ワイ「カリー・・・カレーパンパーソンのことかいな?」
娘「ちがう、カリー化された関数書いて」
ワイ「お、おう」
ワイ「分かるで〜」
ワイ「カリー化された関数が欲しい年頃やもんな」
よめ太郎「(分かるんかい)」
よめ太郎「(どんな話の合わせ方や・・・)」
ワイ「ええけど、そんなもん何に使うんや」
娘「カリー化された関数を部分適用して」
娘「3を足すだけの関数を作ってほしいの」
ワイ「え、ええ・・・?」
娘「みんな持ってるの」
娘「私だけ持ってないの」
ワイ「(いや、そのセリフはおねだりの常套句やけど)」
ワイ「(この文脈では無茶やろ・・・)」
ワイ「(いや、最近の子はホンマにみんな関数を持ってるんか・・・?)」
ワイ「(・・・まあ、娘ちゃんが喜ぶならどっちでもええか・・・)」
ワイ「わ、分かるで〜」
ワイ「ワイが子供の頃も3を足すだけの関数が流行ったもんや」
よめ太郎「(分かり過ぎやろ)」
よめ太郎「(もはや何でも分かる人になってるやん)」
よめ太郎「(ていうかもう、筆者が書きたいことを書くためにストーリーむちゃくちゃなってるやん・・・)」
ワイ「さあ、関数をカリー化していくで〜」
カリー化とは
ワイ「たしか、カリー化いうんは」
function tashizann(hikisu1, hikisu2) {
return hikisu1 + hikisu2;
}
ワイ「例えば↑こういう普通の足し算関数を」
tashizann(3, 5);
ワイ「↑こういう風に2つの引数を渡すんやなくて」
tashizann(3)(5);
ワイ「↑こういう風に1つずつ引数を渡す関数に変換することやったな」
ワイ「そうするには・・・」
ワイ「どないすればええんや」
ワイ「要はtashizann(3)
の部分が、戻り値として関数を返してくれれば」
ワイ「返ってきたその関数に、引数として5
をぶち込んで」
ワイ「実行してやればええねんな」
ワイ「ということは・・・」
function tashizann(hikisu1) {
}
ワイ「↑こんな感じで」
ワイ「tashizann
が最初に受け取る引数は1つだけ」
ワイ「今回の例で言えば3
だけを受け取るようにする、と」
ワイ「ほんで」
function tashizann(hikisu1) {
return function(){
}
}
ワイ「↑こうや」
ワイ「tashizann
は戻り値として関数を返すんや・・・」
ワイ「ほんで、その返した関数に5
をぶち込みたいから」
ワイ「内側の関数にも引数を1つ指定せなあかんのやな」
function tashizann(hikisu1) {
return function(hikisu2){
}
}
ワイ「こうや」
ワイ「これでhikisu2
に5
が入ってくるはずや」
ワイ「ほんで、その内側の関数が最終的に返す値は」
ワイ「3 + 5
やから・・・」
ワイ「return hikisu1 + hikisu2;
ってしてやればええんやな?」
function tashizann(hikisu1) {
return function(hikisu2){
return hikisu1 + hikisu2;
}
}
ワイ「↑こうやな」
ワイ「試してみよか」
const kekka = tashizann(3)(5);
alert(kekka);
アラート結果:
8
ワイ「おお」
ワイ「とりあえず、2つの引数を受け取るtashizann
関数を」
ワイ「1つの引数を受け取る関数をネストしたものに変換できたで」
Next: 部分適用
ワイ「カリー化は出来たから、次は部分適用や」
ワイ「さっきカリー化した関数を使って、3を足すだけの関数を生成すればええんやな」
ワイ「さっきのtashizann
という関数に3
だけを渡すと」
ワイ「関数が返ってくるはずやから」
ワイ「その返ってきた関数を定数に入れて保存しとけばええんや」
const tasu3 = tashizann(3);
ワイ「↑こうやな」
ワイ「これで、tashizann
を部分適用してtasu3
いう関数を作ることが出来たはずやで」
ワイ「実際にtasu3
を使って、試してみよか」
const kekka2 = tasu3(5);
alert(kekka2);
アラート結果:
8
ワイ「おお、できたで」
娘(3歳)「わーい!」
娘「これで3を足し放題だ〜!!!」
ワイ「・・・ホンマにこんなもんが欲しかったんか?」
娘「何言ってるの」
娘「実務でもけっこう使えるよ?」
ワイ「(実務!?)」
ワイ「(義務教育もまだやのにもう実務を視野に・・・!?)」
ワイ「(末恐ろしい子やな・・・)」
娘「HaskellやElmなんかだと、関数がデフォルトでカリー化されてるんだから」
ワイ「せ、せやな(知らんけど)」
そんなこんなで晩ごはん
ワイ「いただきますやで〜」
ワイ「はぁ、明日から新しい職場で働くんやな〜」
ワイ「ワイはちゃんとやっていけるんやろか」
ワイ「同僚のみんなのレベルについていけるんやろか」
ワイ「毎日プログラミングのお勉強はしとるけど、それでもまだ不安や・・・」
娘「パパ」
娘「前もって先のことを考えたり、心配しておくのは」
娘「基本的には良いことだと思うけど」
娘「それで考えすぎて心が疲れちゃうくらいなら」
娘「いったん考えるのをやめて、今このご飯が美味しいってことにフォーカスを当ててみよ?」
娘「まだ来てない明日のことで傷つくより、」
娘「目の前にあるご飯の美味しさを、集中して味わおうよ」
娘「そのほうが心も安らいで、むしろ明日の力になるんだよ」
ワイ「せやな・・・」
ワイ「ありがとう娘ちゃん・・・」
ワイ「ウマい・・・ウマいで・・・」
よめ太郎「(できた子や・・・)」
よめ太郎「(ワイの血やな・・・)」
〜おしまい〜
追記1: アロー関数式
アロー関数式を使って書くとここまでシンプルにできるで。
const tashizann = hikisu1 => hikisu2 => hikisu1 + hikisu2;
追記2: カリー化や部分適用のメリット
例えば
const styleChange = prop => value => elm => elm.style[prop] = value;
↑こんな関数を作っておいて、
document.querySelectorAll(".className").forEach(styleChange("color")("red"));
↑こんな感じで即席関数を作ってforEachメソッドに渡せたり・・・とかですかね。
ぶっちゃけ使い所はあんまり分かってません・・・。