Утрата ссылочной прозрачности при присваивании
Зависимость от предыстории, зависимость от порядка и чувствительные к псевдонимам наблюдения, когда вызовы меняют сохраненные ячейки памяти.
Какие рассуждения о подстановке и изменении порядка становятся неверными, когда выражение может изменять состояние?
- Сравнение повторных вызовов с состоянием и повторных чистых вызовов
- Распознавание того, что одинаковые выражения исходного кода со временем могут давать разные значения
- Явное задание двух расписаний вычисления вместо опоры на порядок операндов
- Наблюдение за тем, как более ранний вызов изменяет смысл последующего вызова
- Фиксация точного конечного расписания и порядка его вычисления
Два вызова одной и той же процедуры withdraw с одним и тем же аргументом возвращают 90, а затем 80, поскольку первый вызов изменяет захваченный balance. Поэтому замена обоих вызовов одним ранее вычисленным значением изменила бы программу. Чистая процедура withdraw-value не имеет скрытой предыстории, поэтому два вызова с одним и тем же явным balance возвращают 90.
Зонд порядка делает зависимость от расписания явной с помощью связываний let. Сначала вызов с сообщением 0 изменяет состояние, а затем сообщение 1 считывает его. Если первым вызывается сообщение 1, оно наблюдает прежнее состояние. Ни один из выводов здесь не зависит от того, какой порядок операндов выбирает вычислитель. Обе последовательности записаны раздельно и сравниваются как данные.
- Вывод
- —
- Значение
- —
- Диагностика
- —
Программа с повторениями возвращает (90 80 90 90). Явные расписания возвращают ((0 1 1) (0 0 0)).
Найдите присваивание balance между двумя одинаковыми вызовами с состоянием, а затем убедитесь, что чистые вызовы не создают постоянной ячейки памяти. При сравнении расписаний проследите за первым вызовом перед вторым и определите точную операцию чтения, значение которой изменяется.
Измените программу и сравните результат.
Добавьте сообщение reset в зонд порядка и сравните zero-reset-one с zero-one-reset. Объясните, какая алгебраическая подстановка или изменение порядка вызовов изменили бы каждое из наблюдений.
Показать подсказку
Запишите каждый вызов во вложенном let, чтобы расписание стало частью исходного кода, а не предположением о вычислении аргументов.