Песочница

Данные, условия и решения

Сохраняйте символы и списки как данные, выбирайте через if и cond, используйте короткое замыкание и возвращайте решение с понятной меткой.

Когда программы способны различать код и данные, а также выбирать один результат, они выполняют полезную работу. Лиспекс оставляет обе идеи на виду. Цитирование сохраняет данные, а условные конструкции решают, какое выражение вычисляется.

Цитирование сохраняет форму как данные

Без апострофа Лиспекс считает непустой список подлежащим вычислению.

LISPEX
(+ 1 2)

С апострофом Лиспекс возвращает ту же форму как данные.

LISPEX
'(+ 1 2)

Результат

OUTPUT
(+ 1 2)

Новый список также можно построить из вычисленных значений.

LISPEX
(list 'decision 'allow)

Результат

OUTPUT
(decision allow)

Цитируйте фиксированные литеральные данные. Используйте list, если один или несколько элементов нужно вычислить.

if делает один двусторонний выбор

У if есть тест, результат для истины и результат для лжи.

LISPEX
(if (>= 62 50)
    '(decision free-shipping)
    '(decision standard-shipping))

Вычисляется только выбранная ветвь. Ложен только #f. Значения 0, "" и () истинны. Если вам нужен смысл «непусто», «положительно» или другое условие предметной области, используйте явный предикат, то есть проверку, которая отвечает «истина» или «ложь».

and и or останавливаются раньше

and вычисляет выражения слева направо и останавливается на #f. or останавливается на первом истинном значении. not переворачивает полученную истину или ложь.

LISPEX
(and (<= 9 14)
     (not #f))

Результат

OUTPUT
#t

Короткое замыкание входит в правило вычисления. Выражение справа не вычисляется, если ответ уже известен.

Значение, на котором вычисление остановилось, и становится ответом. В логическое оно не превращается.

LISPEX
(or #f 'standard)

Результат

OUTPUT
standard

cond называет несколько случаев

LISPEX
(define (shipping-decision total member?)
  (cond
    ((>= total 50) '(decision free-shipping))
    (member? '(decision discounted-shipping))
    (else '(decision standard-shipping))))

(shipping-decision 42 #t)

Результат

OUTPUT
(decision discounted-shipping)

Условия проверяются сверху вниз. Большая сумма выигрывает до проверки участника. else задаёт запасной путь. Подписанный список показывает читателю, что означает ответ, не требуя знания процедуры, которая этот ответ получила.

При необходимости разберите список

Для обычного списка, который заканчивается пустым списком, car возвращает первое значение, а cdr возвращает оставшийся список.

LISPEX
(define answer '(decision allow))
(list (car answer) (car (cdr answer)))

Результат

OUTPUT
(decision allow)

В обычных правилах предпочитайте прямое построение и предикаты. Цепочки car/cdr, собранные вручную, полезны для обучения и низкоуровневого доступа, но именованные помощники часто передают намерение лучше.

Упражнение

Напишите age-decision так, чтобы для возраста 18 и выше возвращалось (decision allow), а для меньшего возраста возвращалось (decision deny under-age).

Показать один ответ
LISPEX
(define (age-decision age)
  (if (>= age 18)
      '(decision allow)
      '(decision deny under-age)))

(age-decision 17)

В результате получается (decision deny under-age).

Готовы к шагу 5?

Продолжайте, когда сможете объяснить разницу между '(decision allow) и (decision allow), назвать три позиции if и сказать, почему 0 не является ложью. Дальше идёт Первое решающее правило.