Песочница

Как писать условия

Выберите if, cond или case для своей задачи и узнайте, какие выражения будут вычислены.

Выберите условную форму

Используйте if для одного вопроса «да или нет», cond для нескольких условий, а case для сравнения значения с фиксированными данными. Здесь вы узнаете, какие выражения вычисляет каждая форма. Формы вроде cond и case, которые выполняются через преобразование в другие формы, называются производными формами.

Проверьте запуском

LISPEX
(case 2 ((1) 'one) ((2) 'two) (else 'other))

Наблюдаемый результат

ВЫВОД
two

case вычисляет 2 один раз и выбирает вторую ветвь. Результат — символ two. Тела остальных ветвей не вычисляются.

LISPEX
(if #t 42 (/ 1 0))
(cond ((< 3 0) (/ 1 0))
      ((< 3 5) 'small)
      (else 'large))

Наблюдаемый результат

42
small

if вычисляет условие, затем только выбранную ветвь. cond проверяет условия по порядку и выполняет тело первой ветви с истинным условием. Остальные ветви пропускаются вместе с их условиями. Ни одно деление в этом примере не выполняется.

Запустите каждый блок на площадке. Полученные значения появятся отдельными строками, как показано выше.

Как читать формы

Форма — это единица синтаксиса программы, например (if #t 1 0). Datum — отдельный элемент данных, например число, символ или список. В case данные каждой ветви сравниваются с ключом через eqv?. Они не вычисляются как выражения.

Только #f считается ложным. Все остальные значения считаются истинными.

ФормаКогда применятьРезультат
ifодно условие выбирает из двух ветвейзначения выбранной ветви
condразные случаи описаны несколькими условиямизначения первой подходящей ветви
caseодно значение сравнивается с фиксированными даннымиключ вычисляется один раз, затем выполняется подходящая ветвь
and / orследующая проверка зависит от предыдущихостановка на первом ложном / истинном значении, результатом служит значение операнда
when / unlessтело нужно выполнить лишь в одном случаеноль значений, если тело пропущено

and и or прекращают вычисление, как только результат известен. Это называется сокращённым вычислением. Они возвращают значение операнда без преобразования в булево значение.

Выполнение тела по условию

when выполняет тело по порядку, если условие истинно. unless выполняет тело, если условие ложно. Каждая форма возвращает результат последнего выражения тела.

(when #t 42) возвращает 42, а (unless #f 7) возвращает 7. Если тело пропущено, форма возвращает ноль значений. У when это происходит при #f, а у unless — при истинном условии.

Для обработки перехватываемой ошибки используйте (guard (переменная ветвь ...) тело ...). guard связывает перехваченный объект с переменной и проверяет ветви по порядку, как cond. Последняя ветвь else обрабатывает оставшиеся случаи. Если ни одна ветвь не подошла, guard повторно возбуждает исходную ошибку.

Проверка синтаксиса перед запуском

  • Для if нужны условие и обе ветви. (if #t 1) выдаёт E130, поскольку ложная ветвь отсутствует.
  • Если в cond или case нет подходящей ветви и нет else, результат содержит ноль значений. Его использование там, где нужно одно значение, вызывает E320.
  • else имеет особый смысл в начале ветви cond, case или guard. Это не зарезервированное слово, поэтому (define else 5) допустимо.
  • cond отвергает стрелочную ветвь с =>, выдавая E130. В теле ветви case запись => означает обычное имя. Если оно не связано, его вычисление вызывает E300.
  • unquote и unquote-splicing вне квазицитирования вызывают статические ошибки, которые обнаруживаются до выполнения.

Пропустить ветвь означает не вычислять её. Перед запуском Лиспекс всё равно проверяет синтаксис всей программы.

Как выполняются сокращения

Перед выполнением Лиспекс преобразует сокращённую запись в основные формы. Этот шаг называется нормализацией. Правила для cond, case, and, or, when, unless, let*, именованного let, do и квазицитирования встроены в язык.

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

Лиспекс раскрывает формы по встроенным правилам. define-syntax и пользовательские макросы отвергаются.

Куда дальше

Потренируйтесь выбирать условия в уроке Данные и решения. Преобразование сокращений описано в справочнике Синтаксис, который раскрывается в базовые формы.