Песочница

Работа с map, filter, fold и apply

Стройте детерминированные pipeline из обхода коллекций слева направо и явно задавайте арность callback и контексты результатов.

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

LISPEX
(reduce + 0 (map (lambda (x) (* x x)) (filter odd? (list 1 2 3 4))))

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

OUTPUT
10

Разберите приём

  1. Отберите. filter сохраняет 1 и 3, для которых odd? истинен.
  2. Преобразуйте. map возводит оставшиеся значения в квадрат и получает (1 9) в том же порядке.
  3. Сверните. reduce начинает с 0, складывает квадраты и получает 10.

Как рассуждать

  • Используйте map для одного результата на элемент, filter для выбора и folds для одного аккумулятора.
  • Используйте all? или any?, если строгий boolean позволяет остановить обход раньше.
  • Callbacks выполняются как гостевые процедуры, поэтому действуют ошибки, escapes, предупреждения и value contexts.
  • string-map и vector-map создают новые коллекции; варианты for-each выполняют только эффекты и возвращают ноль значений.
  • Используйте apply, когда последний правильный список должен стать позиционными аргументами; хвостовое применение сохраняется.

Проверьте себя

Что вернёт тот же конвейер, если заменить odd? на even??

Ответ

Он оставит 2 и 4, преобразует их в (4 16) и вернёт 20.

Частая ошибка

Callback, дающий ноль или несколько значений в позиции одного значения, вызывает E320.

Куда дальше

Точная арность callback указана в справочнике. Используйте рекурсию, если поддерживаемые комбинаторы не выражают обход ясно.

Справочник высшего порядка · Руководство по рекурсии