反转LISP列表到位

反转LISP列表到位,lisp,Lisp,我想写一个函数来反转列表中的元素,但是它应该在适当的位置发生(也就是说,不要创建一个新的反转列表) 比如: >> (setq l ' (a b c d)) ((a b c d) >> (rev l) (d c b a) >> l (d c b a) 要实现这一点,我应该遵循哪些标志?请查看nreverse,它将修改列表(请参阅) 根据注释,注意@Barmar的注释和规范中的这一点: 对于nreverse,序列可能会被销毁并重新用于生成结果。结果可能与序列相同

我想写一个函数来反转列表中的元素,但是它应该在适当的位置发生(也就是说,不要创建一个新的反转列表)

比如:

>> (setq l ' (a b c d))
((a b c d)
>> (rev l)
(d c b a)
>> l
(d c b a)

要实现这一点,我应该遵循哪些标志?

请查看
nreverse
,它将修改列表(请参阅)

根据注释,注意@Barmar的注释和规范中的这一点:

对于nreverse,序列可能会被销毁并重新用于生成结果。结果可能与序列相同,也可能不相同。具体来说,当序列是一个列表时,nreverse允许设置序列列表结构中任何CON的任何部分(car或cdr)


查看
nreverse
,它将修改列表(请参阅)

根据注释,注意@Barmar的注释和规范中的这一点:

对于nreverse,序列可能会被销毁并重新用于生成结果。结果可能与序列相同,也可能不相同。具体来说,当序列是一个列表时,nreverse允许设置序列列表结构中任何CON的任何部分(car或cdr)


实现这一点并不困难(忽略故障案例)。关键是使用
(setf cdr)
重用给定的cons单元,并且不丢失对先前cdr的引用

(defun nreverse2 (list)
  (recurse reving ((list list) (rslt '()))
    (if (not (consp list))
        rslt
        (let ((rest (cdr list)))
          (setf (cdr list) rslt)
          (reving rest list)))))

(defmacro recurse (name args &rest body)
  `(labels ((,name ,(mapcar #'car args) ,@body))
     (,name ,@(mapcar #'cadr args))))
[编辑]如评论中所述,要真正做到这一点(不考虑):


实现这一点并不困难(忽略故障案例)。关键是使用
(setf cdr)
重用给定的cons单元,并且不丢失对先前cdr的引用

(defun nreverse2 (list)
  (recurse reving ((list list) (rslt '()))
    (if (not (consp list))
        rslt
        (let ((rest (cdr list)))
          (setf (cdr list) rslt)
          (reving rest list)))))

(defmacro recurse (name args &rest body)
  `(labels ((,name ,(mapcar #'car args) ,@body))
     (,name ,@(mapcar #'cadr args))))
[编辑]如评论中所述,要真正做到这一点(不考虑):


请注意,您需要将其重新分配给变量,例如
(setq l(nreverse l))
。它重用原始列表元素,但不同的cons可能是结果的开头。请注意,您需要将其重新分配给变量,例如
(setq l(nreverse l))
。它重用原始列表元素,但不同的cons可能是结果的开头。这会回收cons单元格(因此它被恰当地称为
nreverse2
(n表示不一致)),但它不会在适当的位置反转列表。作为原始列表标题的cons不是反向列表的标题。例如,
(let((l(列表1 2 3))(nreverse2 l)l)
产生
(1)
。它回收cons单元格(因此它被恰当地称为
nreverse2
(n表示不考虑)),但它不会在适当的位置反转列表。作为原始列表标题的cons不是反向列表的标题。例如,
(let((l(列表1 2 3)))(nreverse2 l)l)
产生
(1)