Когда это нужно
Порядок важен, когда выражение изменяет ячейку, печатает, выдаёт ошибку или может быть пропущено. Лиспекс фиксирует этот порядок, поэтому результат не зависит от соглашений языка-хозяина.
Проверьте запуском
(define x 0)
(list (begin (set! x 1) x) (begin (set! x (+ x 1)) x))Наблюдаемый результат
(1 2)Разбор примера
Первый begin меняет x с 0 на 1 и возвращает 1. Только после этого второй операнд читает новое значение, прибавляет единицу, сохраняет 2 и возвращает его. Поэтому list получает сначала 1, а затем 2.
Как рассуждать
- Инициализаторы
letвычисляются слева направо во внешнем окружении.let*расширяет окружение по одному связыванию, аletrecсначала выделяет все ячейки. - Последовательности вычисляются слева направо и отбрасывают пакеты значений всех выражений, кроме последнего.
andиorвычисляются по короткой схеме слева направо, и ложно только#f.
Быстрый выбор
| Контекст | Порядок | Что может не выполняться |
|---|---|---|
| вызов процедуры | оператор, затем операнды слева направо | ничего |
begin | формы слева направо | ничего, ранние значения лишь отбрасываются |
if | условие, затем одна выбранная ветвь | невыбранная ветвь |
and / or | операнды слева направо | остаток после получения ответа |
let | инициализаторы слева направо во внешней области | ничего |
let* | связывание после каждого инициализатора | ничего |
Частая ошибка
Лиспекс не наследует неопределённый порядок операндов другой реализации Scheme.
Текущие границы
- Ошибка арности возникает после обязательного вычисления оператора и операндов.
Куда дальше
Различия областей let объясняются в главе о связываниях, а раннюю остановку разбирает глава об условиях.