0

所以我试图让一个函数接受一个列表并将其反转,但我不确定我将如何使用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)))))
4

2 回答 2

0

所以一个潜在的列表参数将是(1 2). 我们可以想象参数是地址为#A的列表,它看起来像这样:

#A=(1 . #B)
#B=(2 . nil) 

对于每个缺点,我们cdr在将 设置cdr为前一个之前创建局部变量存储,第一个cons为 nil cons。当当前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 <??> <??>))))
于 2015-02-18T21:09:36.737 回答
0

所以我相信这就是他们正在寻找的答案:

Recursive: 
(define rip (lst)
(if (null lst) nil (nconc (rip (rest lst))(rplacd lst nil))))

Non-Recursive:
(defun rip (lst)
(do ((res nil) (todo (rest lst)(rest lst)))
    ((null lst) res)
  (setf res (rplacd lst res))
  (setf lst todo) ))
于 2015-02-26T16:26:53.977 回答