Использование Reduce над деревом в Лиспе
Чтобы сложить плоский список в Лиспе, вы используетеreduce
:
* (reduce #'+ '(1 2 3 4 5))
15
Но что, если у меня произвольно сложное дерево, и я хочу применить функцию к каждому элементу? Так что переверни'(1 (2) (3 (4) 5))
все равно даст15
? Я пытался использоватьreduce
, но я должен был предоставить пользовательскую функцию, которая как бы побеждает цель:
(defun tree+ (a b)
(cond ((null b) 0)
((atom b) (+ a b))
(t (+ (tree+ a (car b))
(tree+ 0 (cdr b))))))
(reduce #'tree+ '(1 (2) (3 (4) 5)) :initial-value 0) ; returns 15
Конечно, я мог бы сначала сгладить список, ноreduce
это общая функция, иногда вы должны сохранить структуру и порядок исходной последовательности. Например,map
а такжеfilter
может быть реализован сreduce
, Что если бы я хотел написать реализациюmy-map
на основеreduce
, чтобы:
(my-map '1+ '(1 (2 (3) 4) 5)) ; outputs '(2 (3 (4) 5) 6)
Как пользоватьсяreduce
над древовидной структурой? Какой самый общий способ применения бинарной функции к дереву?