JavaScript おれおれ Advent Calendar 2011 – 2日目

※飛べません。

今日はちょっと挑戦的な記事。僕の理解が足りてないかも。

世の中には「カリー化」という技術があります。

関数を分解して、引数がひとつの関数の入れ子にする事です。fn(a, b, c)がfn(a)(b)(c)になります。よくわからんと思うのですが、ちょいと実例を見てみましょう。

まず、二つの引数を取る関数を考えます。ちょうど昨日やったゼロフィルを関数化します。

function fillZero(digits, num) {
  var text = "";
  for (var i = 0; i < digits-1; i++) {
    text += "0";
  }
  return (text + num).slice(-digits);
}

で、これをカリー化して、fn(digits)(num)と書けるようにします。

function fillZeroCurried(digits) {
  return function(num) {
    var text = "";
    for (var i = 0; i < digits-1; i++) {
      text += "0";
    }
    return (text + num).slice(-digits);
  };
}

できました。こんな感じで使えます。

console.log(fillZero(4, 12));  // => "0012"
console.log(fillZeroCurried(4)(12));  // => "0012"

で、この関数を使って部分適用した関数を使って、昨日と同じものを表示してみましょう。

var fillZero2 = fillZeroCurried(2);
var fillZero4 = fillZeroCurried(4);

var now = new Date();
var timeText = [
  fillZero2(now.getHours()),
  fillZero2(now.getMinutes()),
  fillZero2(now.getSeconds()),
  fillZero4(now.getMilliseconds())
  ].join(':');
console.log(timeText);

注意とか

カリー化

カリー化と部分適用の解釈は足りないかもしれません。コメントでご指摘頂けると助かります。

ちなみにJavaScript: The Good Partsで紹介されてる「カリー化」は部分適用なんじゃないかなあって思います。

曰く:

4.14 カリー化

JavaScriptにおける関数は値である。そしてこの関数値は、興味深い操作を行うことができる。カリー化は、関数に引数を固定して新しい関数を生成する。

var add1 = add.curry(1);
document.writeln(add1(6)); // 7

これじゃないカリー

カリー化 (currying) は論理学者Haskell Brooks Curryに因んで名付けられたそうです。

  • 食べ物のカレーもcurryですが、別物です。
  • ものを運ぶのはcarryです。キャリーです。
  • arguments.calleeはたぶん「コーリー」です。call, caller, calleeの関係です。 employee的な。

処理内容

  • 数値が桁数を超えている場合はおかしくなります。今回はそこは主題じゃないので省略してます。
  • "000..."の生成を毎回やってますが、これもクロージャに閉じ込めておくと良さそうです。今回はそこは主題じゃないので以下略。
  • カリー化済みの関数名、もっと良いのないかなあと思ったんですが、今回はそこは以下略。

JavaScript?

|・ω・) .oO( あんまり関係なかったかも……。

参考