Изменяемые или неизменяемые замыкания
-
23-08-2019 - |
Вопрос
В императивном объектно-ориентированном языке имело бы больше смысла иметь изменяемые или неизменяемые замыкания?
Например:
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();
Итак, что лучше: иметь изменяемые или неизменяемые замыкания, или иметь возможность и того, и другого?Неизменяемые замыкания кажутся более простыми в реализации, поэтому на данный момент я думаю, что пойду на это, если только нет веской причины не делать этого.
Решение
Императивные языки обычно строятся вокруг концепции государства.Следовательно, имеет больше смысла отражать это в функциях языка, включая замыкания.Да, такое поведение иногда может сбивать с толку, но это часть проблемы и преимущество наличия состояния в вашем приложении.
Я думаю, что лучшим доказательством этого аргумента будет рассмотрение некоторых последних языков, в которых есть поддержка замыканий.И C#, и VB.Net, императивные объектно-ориентированные языки, решили использовать изменяемые замыкания.В то время как F#, функциональный язык, имеет неизменяемые замыкания (в основном это связано с идеей, что F# неизменяем по умолчанию).
И что на самом деле означало бы наличие неизменяемого замыкания в императивном языке?Большинство людей думают об этом как о том, что переменные эквивалентны переменным C#, доступным только для чтения.Конечно, типы значений будут защищены от изменений, но как насчет изменяемых ссылочных типов?Вы не сможете изменить место, на которое указывает переменная, но можете вызвать мутирующую функцию и получить аналогичный эффект.Например.
class Student {
public string Name { get; set; }
}
void Example() {
var student = new Student() { Name = "foo" };
Action() del = () =>
{ student.Name = "bar"; };
del();
}
Это можно реализовать с помощью неизменяемого замыкания, поскольку я фактически не изменяю, куда указывают переменные.Однако я явно все еще выполняю операцию по мутации.
Другие советы
Должны ли языки иметь лямбды, которые захватывают по значению или по ссылке?Решайте сами, а смотрите»О лямбда-выражениях, захвате и изменчивости", чтобы получить дополнительные комментарии.