Проверьте запуском
(let* ((x 6) (y (+ x 1))) (* x y))Наблюдаемый результат
42let* сначала связывает x, затем использует его значение для вычисления y. Перед выполнением Лиспекс преобразует эти связывания во вложенные формы let.
(let ((x 6))
(let ((y (+ x 1)))
(* x y)))Наблюдаемый результат
42Запустите оба примера на площадке. Каждый возвращает 42.
Что делает нормализация
Форма — это единица синтаксиса программы. Производная форма — сокращённая запись, которую Лиспекс преобразует в основные формы. Это преобразование называется нормализацией.
При преобразовании создаются внутренние имена, которые не могут конфликтовать с именами вашей программы. Также используются скрытые встроенные операции. Например, ваше определение eqv? не меняет способ сравнения данных в case. Такая защита имён называется гигиеной.
Нормализация сохраняет порядок вычисления, хвостовые позиции и диагностику, связанную с исходным текстом. Выражение находится в хвостовой позиции, если его результат возвращается сразу, без дальнейших действий в текущем вызове.
Во что превращается сокращённая форма
| Записанная форма | Преобразование в основные формы | Правило вычисления |
|---|---|---|
cond / case | вложенные формы if с новыми временными именами; case использует скрытый eqv? | хвостовая позиция последнего выражения каждой ветви сохраняется; cond => отвергается |
and / or | вложенные формы if, останавливающие вычисление, когда результат известен | последний операнд сохраняет хвостовую позицию |
when / unless | if с begin для тела или с values без аргументов | ноль значений, если тело пропущено |
именованный let / do | цикл letrec с защитой от конфликтов имён | рекурсивный вызов находится в хвостовой позиции |
quasiquote | quote и скрытые операции создания данных | отдельный unquote вне квазицитирования вызывает статическую ошибку E1xx |
В case datum — отдельный элемент данных, например число, символ или список. Данные ветвей сравниваются через eqv? без вычисления как выражений.
guard обрабатывает перехватываемые ошибки через отдельную основную форму. Его синтаксис и правила обработки тоже встроены в язык.
Встроенные правила синтаксиса
Лиспекс применяет встроенные правила преобразования до вычисления. define-syntax, синтаксические объекты и произвольное пользовательское раскрытие отвергаются. Пропуск ветви при выполнении не отменяет проверку её синтаксиса.
Куда дальше
Получившийся синтаксис описан в справочнике Базовые формы синтаксиса. Выбрать между if, cond и case поможет раздел Как писать условия.