Зачем делать переменную неизменной и создавать новую запись при переопределении переменной? - PullRequest
0 голосов
/ 08 мая 2020

В SML, если я прав, переменные по умолчанию неизменяемы. Поэтому, когда мы пытаемся переопределить переменную

val y  = 100;
val y = 0.6;
y

, в среде будет две записи для y. Новая запись скрывает исходную запись. Разве это не тот же эффект, как если бы мы изменили значение в исходной записи со 100 на 0,6?

  • Если исходная запись была создана вне вызова функции, а новая запись была создается в вызове функции, то, когда вызов функции возвращается, мы можем получить доступ к исходной записи.

  • Если обе записи были созданы в одной «области», как в примере выше, это исходная запись недоступна?

Фактически, разве это не то же самое в SML и в императивном языке, таком как C? Какой смысл делать переменную неизменной в SML и создавать новую запись при переопределении переменной?

Спасибо.

Ответы [ 2 ]

3 голосов
/ 08 мая 2020

Чтобы изменить ответ kopecs:

Какой смысл делать переменную неизменной в SML и создавать новую запись при переопределении переменной?

То есть неправильная формулировка вопроса. :) Неизменяемость по умолчанию имеет много достоинств, но это было бы не так. c.

Фактический вопрос: почему SML допускает множественные привязки для одной и той же переменной в одной области? Вместо того, чтобы выдавать ошибку?

И это справедливый вопрос. Нет никакой серьезной причины. Просто иногда это бывает удобно. Например, чтобы избежать ложных конфликтов идентификаторов при использовании open. Или разрешить переопределение предыдущих определений в интерактивном сеансе.

3 голосов
/ 08 мая 2020

Разве это не тот же эффект, как если бы мы изменили значение в исходной записи с 100 на 0,6

Нет. Рассмотрим код, который ссылается на предыдущую среду с помощью замыкания, например

val x = 7
val f = fn () => x
val x = 8
val _ = print (Int.toString (f ())) (* prints 7 *)

Если исходная запись была создана вне вызова функции, а новая запись была создана при вызове функции, тогда, когда вызов функции возвращается, мы можем получить доступ к исходной записи.

Конечно, ее статическая область действия.

Если обе записи были созданы в одной «области», как в примере выше, исходная запись недоступна?

Она все еще доступна, но не по этому идентификатору. Рассмотрим приведенный выше пример.

Какой смысл делать переменную неизменной в SML и создавать новую запись при переопределении переменной?

Одно из применений этого - изменение тип переменной, но с тем же идентификатором (что вы и делаете в опубликованном вами примере!). Возьмем, к примеру, (в C):

int i = 7;
i = 7.0;

Здесь i по-прежнему будет иметь тип int. См. В SML:

val i : int = 7
val i : real = 7.0

Я добавил аннотации типов для иллюстрации, но даже без этого ведет себя так же. После второй привязки i имеет тип real.

...