手続き型音楽の日常

関数型音楽に乗り換えたい

C#でJavascriptみたいな即時関数を実行する

個人的には、「即時関数」より「即時構文」というほうがしっくり来ます。

名づけ親の本では「即時関数パターン」とされているので、それでもしっくり来ます。

「即時関数」じゃ、少し足らない気がします。

Javascriptでよく使われる即時関数について

まず即時関数というものが何者かを解説します。

ずばり、匿名関数をその場で実行する書き方です。

普通は関数を別に定義して、名前()で呼び出すのが普通ですが、Javascriptでは関数が立派なオブジェクトですので名前をつける必要がありません。そこで、名前を付けずにその場で実行してしまおうという書き方になります。なんとも野心的。

書き方

例1:

var x = (function() { return 1; })();

上記では、xに 1 が代入されます。つまり、function { return 1; }が実行され、その結果が代入されます。

例2:

var x = (function(num) {
    return function(innNum) { return innNum * num; };
})(5);

上記では、xにはfunction(innNum) { return innNum * 5; }が代入されます。

一見「なんだこれ?」ですが、中でfunctionを返しているというところに注目してください。

中のfunction文は即時関数を使っていないので、実行されません。すなわち匿名関数の定義のみ行います。

そして、Javascriptでは匿名関数の定義は評価時に行われるという特徴があります。今回の場合、クロージャの影響でnumに 5 が入っていることを参照してから定義するため、返される匿名関数内のnumは 5 に固定されるのです。

C#で書く

C#は最近、匿名関数だのラムダ式だの、Javascript関数型言語パラダイムを意欲的に取り入れているため、同じように即時関数を書くことができるようです。

Javascriptで挙げた2つの例を、C#で書き直してみます。

例1:

int x = new Func<int>(() => 1)();

C#Javascriptと違って静的な型付け言語のため、匿名関数も型にはめてあげないといけないようです。new Func<int>を省略すると「メソッド名が必要です」というコンパイルエラーが発生します。

例2:

Func<int, int> x = new Func<int, Func<int, int>>((num) => new Func<int, int>((innNum) => innNum * num))(5);

Func<>がとんでもなく多い。さらに、引数と戻り値と型をいちいち指定しなければならない。この場合はちょっと無理がありそうですね。

関数を返すような処理をしなければ、一応使えそうな書き方ですね。