Common lisp 如何替换此循环(循环列表)

Common lisp 如何替换此循环(循环列表),common-lisp,Common Lisp,我想以相反的顺序用相同的元素替换我的循环列表的前几个元素(1 2 3 4 1…)。我已经设法用一个循环来实现它,但我想消除它,而是使用一个处理子序列的公共lisp函数。你能帮我吗 CL-USER> (setf *print-circle* t) T CL-USER> (defvar *cycle* (let ((c (list 1 2 3 4))) (setf (cdr (last c)) c))) #1=(1 2 3 4 . #1#)

我想以相反的顺序用相同的元素替换我的循环列表的前几个元素(1 2 3 4 1…)。我已经设法用一个循环来实现它,但我想消除它,而是使用一个处理子序列的公共lisp函数。你能帮我吗

CL-USER> (setf *print-circle* t)
T
CL-USER> (defvar *cycle*
           (let ((c (list 1 2 3 4)))
             (setf (cdr (last c)) c)))
#1=(1 2 3 4 . #1#)
CL-USER> (let ((reversed-part (list 2 1)))
           (loop for l on *cycle*
              for r in reversed
              do (setf (car l) r))
           *cycle*)
#1=(2 1 3 4 . #1#)
;; Failed attempts:
CL-USER> (let ((reversed-part (list 2 1)))
           (replace *cycle* reversed-part :end1 2 :end2 2)) ;; sets Lisp image spinning forever
CL-USER> (let ((reversed-part (list 2 1)))
           (setf (subseq *cycle* 0 2) reversed-part)) ;; sets Lisp image spinning forever

正如在评论中所说的,大多数处理列表的函数都希望得到正确的列表。不正确的列表(如循环列表)可能会导致无限循环或任何其他不良行为

最好使用显式循环

但是,映射函数如
mapcar
maplist
。。。必须处理不同大小的列表(当最短的一个结束时它们结束),因此只要其中一个参数正确,您通常可以期望映射结束(但是仍然没有保证)。同样,如果提供了
:end
,则subseq可能会终止:

;; IMPORTANT
(setf *print-circle* t)

(defun nrevplace (list start end)
  (mapl (lambda (u v) (setf (car u) (car v)))
        (nthcdr start list)
        (nreverse (subseq list start end))))

(let ((list (list 1 2 3 :a :b :c 4)))
  (setf list (nconc list list))
  (nrevplace list 3 6)
  list)

#1=(1 2 3 :C :B :A 4 . #1#)

如果您在编译时知道替换的大小,那么是您的朋友。谢谢,这是一个变量。不过,我仍在猜测您的想法。请注意,循环列表不是正确的列表,因此不是序列,也不是期望序列的函数的有效输入。这是代码的今天。实际上,我的问题可能被误导了,因为没有代码修复前一个元素的cdr以指向新序列,但我必须注意,我也尝试过替换列表中的下一个元素,例如(替换循环反转部分:start1 1:end2 2)),谢谢您的回答。也许您可以在顶部添加(setf*print circle*t),以防有人(比如我!)忘记这样做而直接运行代码。