2

命令型のオブジェクト指向言語では、ミュータブルまたはイミュータブルなクロージャーを持つ方が理にかなっていますか?

例えば:

int i=5;
function() f={print(i);};
f();
i=6;
f();

クロージャーが変更可能な場合、これは次のように出力されます。

5
6

不変の場合は、次のように出力されます。

5
5

不変のクロージャーを使用しても、これを実行できることを認識しています。

class I {int i;}
I i=new I();
i.i=5;
function() f={
    I j=i;
    print(j.i);
};
f();
i.i=6;
f();

では、ミュータブルまたはイミュータブルなクロージャーを用意した方がよいでしょうか、それとも両方のオプションを用意したほうがよいのでしょうか? イミュータブル クロージャは実装しやすいように思われるので、現時点では、そうしない正当な理由がない限り、それを使用すると思います。

4

2 に答える 2

4

命令型言語は通常、状態の​​概念に基づいて構築されています。したがって、クロージャーを含め、言語機能がそれを反映することはより理にかなっています。はい、この動作は時々混乱する可能性がありますが、これは問題の一部であり、アプリケーションで状態を持つことの利点です。

この議論の最良の証拠は、クロージャーをサポートしている最近の言語のいくつかを見ることだと思います。命令型 OO 言語である C# と VB.Net はどちらも、変更可能なクロージャを持つことを選択しました。一方、関数型言語である F# には不変のクロージャーがあります (主に、F# は既定で不変であるという考えに由来します)。

また、命令型言語で不変のクロージャを持つとは、実際にはどういう意味でしょうか? ほとんどの人は、これを変数を C# の readonly と同等にするものと考えています。確かに値型は変更から保護されますが、変更可能な参照型はどうでしょうか。変数が指す場所を変更することはできませんが、変更関数を呼び出して同様の効果を得ることができます。例えば。

class Student {
  public string Name { get; set; }
}

void Example() {
  var student = new Student() { Name = "foo" };
  Action() del = () => 
    { student.Name = "bar"; };
  del();
}

これは、変数が指す場所を実際に変更しないため、不変のクロージャーで実装できます。しかし、私は明らかにまだ変異操作を行っています。

于 2009-04-04T19:42:27.400 に答える
3

言語には、値によるキャプチャまたは参照によるキャプチャのラムダが必要ですか? 自分で決めてください。詳細については、「ラムダ、キャプチャ、可変性について」を参照してください。

于 2009-04-04T19:47:09.683 に答える