Проверьте запуском
LISPEX
(reduce + 0 (map (lambda (x) (* x x)) (filter odd? (list 1 2 3 4))))Наблюдаемый результат
OUTPUT
10Разберите приём
- Отберите.
filterсохраняет1и3, для которыхodd?истинен. - Преобразуйте.
mapвозводит оставшиеся значения в квадрат и получает(1 9)в том же порядке. - Сверните.
reduceначинает с0, складывает квадраты и получает10.
Как рассуждать
- Используйте
mapдля одного результата на элемент,filterдля выбора и свёртки для одного аккумулятора. - Используйте
all?илиany?, если строгий логический ответ позволяет остановить обход раньше. - Обратные вызовы выполняются как гостевые процедуры, поэтому продолжают действовать ошибки, досрочные выходы, предупреждения и правила контекста значений.
string-mapиvector-mapсоздают новые коллекции, а вариантыfor-eachвыполняют только эффекты и возвращают ноль значений.- Эти процедуры принимают одну коллекцию, а не варианты с несколькими списками из некоторых реализаций Scheme.
- Используйте
apply, когда последний правильный список должен стать позиционными аргументами. Хвостовое применение при этом сохраняется.
Проверьте себя
Что вернёт тот же конвейер, если заменить odd? на even??
Ответ
Он оставит 2 и 4, преобразует их в (4 16) и вернёт 20.
Частая ошибка
Обратный вызов, дающий ноль или несколько значений в позиции одного значения, вызывает E320.
Куда дальше
Точная арность обратных вызовов указана в справочнике. Используйте рекурсию, если поддерживаемые комбинаторы не выражают обход ясно.
Справочник по процедурам высшего порядка · Руководство по рекурсии