ijuio
ijuio

Reputation: 91

appending a variable to list of lists using lisp

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

Answers (1)

Sylwester
Sylwester

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

Related Questions