クロージャ(clojure) - JavascriptとC#

Javascript で一見クラスのようなオブジェクト。

function Color(r, g , b){
 this.R = r;
 this.G = g;
 this.B = b;
}

var color = new Color(255, 0 , 0);
alert(color.R); //255
color.R = 128;
alert(color.R); //128
でも、これはクロージャ。

もっと分かりやすい例を挙げる。
function InclementCounter(val){
 this.value = val;
 this.getValue = function(){
  return this.value++;
 }
}
これをもっと簡略化すると、
function InclementCounter(val){
 this.getValue = function(){
  return val++;
 }
}
こうなる。

これを使ってみる。
var ic = new InclementCounter(0);
alert(ic.getValue()); //0
alert(ic.getValue()); //1
alert(ic.getValue()); //2

渡された値(val)が保持されているのだが不可視となっている。
関数オブジェクトのインスタンスが不可視に内部変数を保持しているという動作がクロージャ。

これをC#でクラスとして書くならこんな感じ。
public class InclementCounter
{
    public InclementCounter(int val)
    {
        this.Value = val;
    }

    public int Value
    {
        get;
        protected set;
    }

    public int getValue()
    {
        return this.Value++;
    }
}
上記の Value プロパティを省略することは出来ないので上のJavascriptと全く同じように書くことは不可能。

ただ、C#でクロージャを書けないワケではない。
C# で書くならこんな感じ。
class Program
{
    static void Main()
    {
        Func<Func<int>> getInclementCounter = () =>
        {
            int n = 0;
            return () => n++;
        };

        Func<int> ic = getInclementCounter();

        Console.WriteLine(ic()); //0
        Console.WriteLine(ic()); //1
        Console.WriteLine(ic()); //2

        Console.ReadLine();
    }
}

こっちの方が分かりやすいかな?
class Program
{
    static void Main()
    {
        Func<int> ic = GetInclementCounter();

        Console.WriteLine(ic()); //0
        Console.WriteLine(ic()); //1
        Console.WriteLine(ic()); //2

        Console.ReadLine();
    }

    private static Func<int> GetInclementCounter()
    {
        int n = 0;
        return () => n++;
    }
}


ミスった。上のJavascriptと同じ動作にするならこうだった。
class Program
{
    static void Main()
    {
        Func<int, Func<int>> getInclementCounter = (int n) =>
        {
            return () => n++;
        };

        Func<int> ic = getInclementCounter(0);

        Console.WriteLine(ic()); //0
        Console.WriteLine(ic()); //1
        Console.WriteLine(ic()); //2

        Console.ReadLine();
    }
}
渡された値(n)を保持するための入れモノが無いでしょ!

最近、点で覚えてきたことが線で繋がる感覚を覚える。

0 Comments:

Sony Style(ソニースタイル)
デル株式会社

Recent Posts