我有一个如下定义的列表:
(defparameter testlist '(((a b) (c d)) ((e f) (g h ))) )
我还有一个变量定义为:
(defparameter feature 'u)
我想在(c d)
附加一个功能。
当我尝试:
(setf (nth 1 (nth 0 testlist)) (append (nth 1 (nth 0 testlist)) feature))
testlist
变为:
(((A B) (C D . U)) ((E F) (G H)))
但是,我想要一个非虚线列表。
我无法弄清楚为什么会有这个结果。你能解释为什么或建议一个更好的追加方法,这对初学者来说是可以理解的吗?
答案 0 :(得分:3)
首先关闭feature
不列表。 append
允许最后一个参数为任何内容,但如果最后一个元素本身不是正确的列表,则结果将不是正确的列表。因此:
(append '(1 2) 3) ; ==> (1 2 . 3)
(append '(1 2) '(3 . 4)) ; ==> (1 2 3 . 4)
(append '(1 2) '(3 4)) ; ==> (1 2 3 4)
因此,如果您希望(list feature)
成为要替换的列表中的一个元素而不是新的虚线值,则需要附加feature
。
您需要在需要重新创建之前找到要更改的列表以及所有内容,但只需与原始源共享后即可找到所有内容:
在结果可以共享cadar
的同时,您需要重新设置caar
时,想要更改cdr
的结构:
(let ((lst '(((a b) (c d)) ((e f) (g h )))) (feature 'x))
(list* (list (caar lst) (append (cadar lst) (list feature))) (cdr lst)))
; ==> (((a b) (c d x)) ((e f) (g h)))
现在,您如何选择使用该结果取决于您。您可以setf
绑定,除了不必要的后果之外,您将具有相同的行为。