関数だけで四則演算をやってみた (前編)

四則演算について

今回の記事では、小学校で習った算数を思い出しながら、単純な四則計算をJavaScriptのコードで書いていきたいと思います。もちろん、+や-などの演算子を使わず、関数だけで実装します。

数値の関数

まず、準備として、0、1、2、3...の数字(自然数)を、関数として表現します。

var _0 = function (f) {
           return function (x) {
             return x;
           };
         },
    _1 = function(f) {
           return function(x) {
             return f(x);
           };
         },
    _2 = function(f) {
           return function(x) {
             return f(f(x));
           };
         };

_0関数は、数字の0に当たります。同様に、_ (アンダーバー)を対応する数字の頭につけて、数値の関数ができます。

ToNumber関数

このままだと、console.logでログ出力するときに関数のままだと、困ります。たとえば、console.log(_0)の返り値は、function(f) {...}となりかねません。
そこで、関数を数値に変換するToNumber関数を、前もって、作っておきましょう。

/*関数をJavaScriptの数値オブジェクトに変換*/
var ToNumber = function (f) {
  return f(
    function (x) {
      return x + 1;
    }
  ) (0);
}

このToNumber関数を使えば、以下のように、数値出力もできるようになります。

ToNumber (_0)); // 0
ToNumber (_1)); // 1
ToNumber (_2)); // 2

後者関数

足し算のコードを書く前に、後者関数について説明しておきましょう。Successor関数は、引数に1を足して返す関数です。これを「後者関数」と呼びます。

/*後続関数 引数numに対して、num+1を返す(ただし、関数)*/
var Successor = function(num) {
  return function(f) {
    return function(x) {
      return f(
        num(f)(x)
      );
    };
  };
};

この関数の使い方はかんたんです。さきほど作った数値関数を_0、_1などを引数に入力するだけでOKです。

ToNumber(Successor(_0));            //1
ToNumber(Successor(_1));            //2
ToNumber(Successor(Successor(_0))); //2

続けて、この後者関数を使って、足し算をやっていきましょう。

加法演算

単なる足し算ができるプラス関数を作ります。

var Plus = function (m) {
  return function (n) {
    return n(Successor)(m);
  };
};

プラス関数は、後者関数を何度も呼び出すことで、数を次々と、足していくことができます。たとえば、_2(Successor)ならば、次のような形で呼び出されるでしょう。

 function (x) {
   /*Successor関数が二度、呼び出されている*/
   return Successor( Successor(x) );
 }

ですから、このPlus関数は、次のようにして、二つの数値関数の足し算ができます。

ToNumber(Plus(_0)(_1)); //1
ToNumber(Plus(_1)(_2)); //3
ToNumber(Plus(_2)(_2)); //4

同じようにして、今度は引き算をやってみましょう。

減法演算

前者関数

さきほどの後者関数とは逆に、-1ができる前者関数を前もって作っておきます。

/*前者関数 引数numに対して、num-1を返す。numが0のときは0を返す(ただし、関数)*/
var Predecessor = function (num) {
  return function (f) {
    return function (x) {
      return num (
        function (g) {
          return function (h) {
            return h(g(f));
          };
        }
      ) (
        function (u) {
          return x;
        }
      ) (
        function (u) {
          return u;
        }
      );
    };
  };
};

/*使い方のサンプル*/

ToNumber(Predecessor(_0));              //0
ToNumber(Predecessor(_1));              //0
ToNumber(Predecessor(Predecessor(_2))); //0

今度は引き算ができるマイナス関数として、Minus関数を書きます。

var Minus = function (m) {
  return function(n) {
    return n(Predecessor)(m);
  };
};

使い方はPlus関数と同じです。

ToNumber(Minus(_0)(_1)); //0
ToNumber(Minus(_2)(_1)); //1
ToNumber(Minus(_2)(_0)); //2

後編に続く

続きは次回の後編で書きます。次回は、関数だけで積を求めてみましょう。次回「関数だけで四則演算をやってみた (後編)