所以我试图让一个函数接受一个列表并在原地反转,但我不确定我将如何使用 RPLACA
/RPLACD
/NONC
。基本上与 reverse 做同样的事情,但它使用原始列表的 cons 节点并且不分配任何新的 cons 节点。到目前为止我所拥有的是
(defun rip(lst)
(cond (( null lst) 0)
((eq (nil) (cdr (last lst))) 1)
(((setq x (car (last lst)))
(rplaca (car (last lst)) (car first lst))
(rplaca (car first lst) x)) + 2 rip(butlast(rest lst)))))
因此一个潜在的列表参数将是 (1 2)
。我们可以想象参数是地址为#A 的列表,它看起来像这样:
#A=(1 . #B)
#B=(2 . nil)
在将 cdr
设置为之前的 cons
之前,我们为每个 cons 创建了存储 cdr
的局部变量,第一个 为 nil缺点
。当当前 cons
为 nil
时,您就完成了,结果是之前的 cons
。我们示例的结果是:
#A=(1 . nil)
#B=(2 . #A)
您唯一需要的变异函数是 rplacd
,因为唯一改变的是 cdr
。该函数可能看起来像这样:
(defun nreverse (list)
(labels ((aux (list prev)
(if (endp list)
<??>
(let ((next <??>))
(rplacd <??> <??>)
(aux <??> <??>)))))
(aux list nil)))
或者如果你不介意泄漏你可以这样做:
(defun nreverse (list &optional prev)
(if (endp list)
<??>
(let ((next <??>))
(rplacd <??> <??>)
(nreverse <??> <??>))))
我是一名优秀的程序员,十分优秀!