Когда это нужно
Создайте процедуру, когда преобразованию нужно имя или его требуется передать другой процедуре. Именованная сокращённая форма читается проще. lambda удобна для локального поведения.
Проверьте запуском
(define (sum first . rest) (apply + first rest))
(sum 1 2 3 4)Наблюдаемый результат
10Разбор примера
sum требует хотя бы один аргумент. first получает 1, а rest получает новый список (2 3 4). apply объединяет явный первый аргумент с этим списком и один раз вызывает +.
Идущие подряд формы define в самом начале тела процедуры создают имена, видимые только внутри неё. Они могут вызывать друг друга.
(define (g)
(define a 1)
(define b 2)
(+ a b))
(g)Наблюдаемый результат
3Так собирается только непрерывный участок в начале. define после какого-нибудь другого выражения значит уже иное, поэтому держите определения вместе наверху.
Как рассуждать
- Несовпадение арности даёт E302 до начала тела процедуры.
- Точечный параметр остатка получает новый правильный список оставшихся аргументов.
- Список параметров
lambdaимеет ровно две формы,(x ...)и(x ... . rest). Голое имя без скобок, как в(lambda args ...), даёт E130. applyпринимает явные начальные аргументы и один последний правильный список, сохраняя хвостовую позицию.
Быстрый выбор
| Форма | Подходящее применение | Арность |
|---|---|---|
(define (f x) body) | именованная повторно используемая процедура | фиксированная |
(lambda (x y) body) | анонимная процедура-значение | фиксированная |
(define (f . xs) body) | именованная процедура собирает свои аргументы | ноль или больше |
(lambda (x . rest) body) | обязательная часть и остаток | не меньше фиксированной части |
(apply f a final-list) | применение аргументов, собранных как данные | проверяет f |
Частая ошибка
Применение непроцедуры даёт E301. Неправильный последний список apply даёт ошибку домена списка.
Текущие границы
- Для выполнения гостевых замыканий не используется
applyсреды.
Куда дальше
Справочник процедур высшего порядка показывает передачу поведения в map, filter и fold, а глава о связываниях объясняет захваченные ячейки.