2009-04-04 3 views
1

В императиве, ориентированном на объект языке, было бы разумнее иметь изменяемые или неизменные закрытия?Mutable или неизменяемые затворы

Например:

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 передавала параметры по ссылке, а версии Visual Basic через VB6 выполнялись аналогично до тех пор, пока vb.net не решила, что передача по значению является лучшим дефолтом, и, несмотря на то, что Microsoft решила, что закрытие должно неявно захватывать переменные по ссылке. Честно говоря, я несколько сомневаюсь в том, что закрытие неявно захватывает переменные вообще (явное объявление переменных, которые нужно уловить, и то, как они должны быть захвачены, будет казаться лучше), но с привязками изменить семантику переменных вызывающего кода кажется особенно хитроумным. – supercat

Смежные вопросы