我一直在寻找这个好几天,基本上我需要实现一个与系统功能减少相同的功能。这是我到目前为止所提出的,但没有初始值i
我无法让它工作。
这是我的代码
(defun my-reduce (p i lista)
(if (null lista)
i
(funcall p (car lista) (my-reduce p i (cdr lista)))))
顺便说一下,它甚至没有正常工作,因为它“向后” 例如:
(my-reduce #'list NIL '(1 2 3 4))
应该返回
(((1 2)3)4)
但我得到
(1(2(3(4 NIL))))
任何想法?
答案 0 :(得分:3)
左侧折叠可以通过简单的迭代实现:
(defun my-fold-left (reducer initial list)
(loop for fold = initial then (funcall reducer fold element)
for element in list
finally (return fold)))
例如:
(my-fold-left #'cons 0 '(1 2 3 4))
((((0 . 1) . 2) . 3) . 4)
(my-fold-left #'cons 0 '())
0
如果使用map
:
(defun my-fold-left (reducer fold sequence)
(map nil
(lambda (e) (setf fold (funcall reducer fold e)))
sequence)
fold)
如果您没有阅读,this answer对左右折叠有一个很好的高级解释。
答案 1 :(得分:1)
我认为你已经实现了正确的右侧折叠,因为这通常被称为,但是需要左侧折叠。注意特征尾递归,并使用“默认”值作为累加器:
(defun my-left-reduce (f i xs)
(if (null xs)
i
(my-left-reduce f (funcall f i (car xs)) (cdr xs))
(我从未使用过Common Lisp,但这个概念应该很明确。)
除此之外:通常是左侧折叠被认为是“向后”。比较(my-reduce cons NIL '(1 2 3))
和(my-left-reduce cons NIL '(1 2 3))
。后者应该颠倒列表的原始缺陷结构。