2009-04-04 24 views
1

不可避的なオブジェクト指向言語では、変更可能または不変クロージャを持つ方が理にかなっていますか?例えば変更可能または不変クロージャ

:閉鎖が可変である場合

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(); 

したがって、変更可能な、または不変のクロージャを使用する方が良いでしょうか、または両方にオプションがありますか?不変のクロージャーは実装が容易であるように見えるので、この時点では、そうしないとよい理由がない限り、私はそれと一緒に行くつもりだと思う。

+0

可変/不変クロージャの用語は少なくともあいまいであり、クロージャ自身を参照する変数が可変/不変であることも意味します。 –

答えて

4

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

私は、この議論の最も良い証拠は、閉包をサポートしている最近の言語のいくつかを見ることだと思います。 C#とVB.Netの両方の命令型OO言語は、変更可能なクロージャを選択しました。関数型言語であるF#は不変のクロージャを持ちますが(主にF#がデフォルトで不変であるという考えから導き出されます)

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

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

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

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

3

値を取得するか、参照としてキャプチャするラムダが必要ですか?あなた自身で決定しますが、さらに解説するには "On lambdas, capture, and mutability"を参照してください。

+0

私は、MicrosoftがQBasicのデフォルトで参照渡しのパラメータを渡すことが不思議であることを知り、VB6によるVisual Basicのバージョンは同様にvb.netが値渡しをより良いデフォルトに決定するまで同様でしたが、参照により。確かに、暗黙のうちに変数を暗黙的に取り込むクロージャーについては疑いがあります(キャプチャする変数の明示的な宣言とキャプチャする方がうまくいくように思われます)が、呼び出しコードの変数のセマンティクスを変更してキャプチャするのは特に面倒です。 – supercat

関連する問題