Reputation: 91
I have a list defined as follows:
(defparameter testlist '(((a b) (c d)) ((e f) (g h ))) )
I also have a variable defined as :
(defparameter feature 'u)
I want to append a feature to (c d)
.
When I try:
(setf (nth 1 (nth 0 testlist)) (append (nth 1 (nth 0 testlist)) feature))
testlist
becomes:
(((A B) (C D . U)) ((E F) (G H)))
However, I want a non dotted list.
I can't figure out why I have this result. Can you explain why or suggest a better method to append, that is comprehensible for a beginner level?
Upvotes: 0
Views: 955
Reputation: 48745
First off your feature
is not a list. append
allows the last argument to be anything but then the result would not be a proper list if the last element is itself not a proper list. Thus:
(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)
Thus you need to append (list feature)
if you want feature
to be one element in the list you are replacing and not the new dotted value.
You need to locate the list you are changing and everything before you need to recreate but everything after you can just share with the original source:
Looking at your structure you want to change the cadar
while you need to recreate the caar
while the result can share the 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)))
Now how you choose to use that result is up to you. You can setf
the binding and you will have the same behaviour as if you mutated except for the unwanted consequences.
Upvotes: 3