Reputation: 235
I need to update values in an association list nested in another association list using setq. I don't know how to do it yet but my first steps in finding out how to do it is not working.
to put simply as simply as possible here is what i've tried:
(defvar l (list 1 2 3))
(loop for x in l do (setq x 5))
im expecting this to update all elements in l to 5 but when i check the value of l it doesn't change at all. If it doesn't work for this example then obviously it's not going to work for my nested alists scenario. How do i loop over l and change the elements? Also if l is not updating then what is (setq x ...) even doing?
EDIT I decided to forge on ahead anyways using a regular list of association lists and im still getting stuck
(defvar u (list (list 1 2) (list 3 4)))
(assoc 1 u)
=> (1 2)
(let ((a (assoc 1 u))) (setf (assoc u 1) (cons (car a) 5)))
im expecting u to change to ((1 5) (3 4)) but im getting an error The function (SETF ASSOC) is undefined. If there's no inbuilt setf form for assoc then surely there's some other inbuilt function for doing this right?
Upvotes: 1
Views: 237
Reputation: 139251
(loop for x in l do (setq x 5))
l
is an outer variable.
x
is a local variable. The loop creates the local variable and binds the list items to the variable in each loop round.
If you set the variable x
, then you just change that variable binding. It has no effect on the list, since x
has its own reference to the elements. It does not reference the list storage cells.
Upvotes: 3
Reputation: 71065
I need to update values in an association list nested in another association list using
setq
.
Not with setq
, ever, which changes a variable's binding; but with (setf (car ...
or (setf (cdr ...
, sometimes (the two are translated into rplaca
and rplacd
).
Why sometimes? Depends whether you have access to the structure itself, or its copy. e.g. (loop for x on l do (setf car x) 5)
does not update l
, but (maplist #'(lambda(x) (setf (car x) 6)) l)
does, as does (setf (car l) 7)
.
Upvotes: 2
Reputation: 27414
First, an association list (reference) is a list in which an element is a cons
pair, whose car
is the so-called key, and the cdr
is the value. So, if you want to build an association list where keys and values are numbers, the correct form is:
(defvar *u* (list (cons 1 2) (cons 3 4))
(assoc 1 *u*) ; => (1 . 2)
In this way, when you want to modify a value associated to a certain key, you can use the rplacd
primitive operation (reference), that replaces the cdr
of a pair found with assoc
. For instance:
(rplacd (assoc 1 *u*) 5)
*u* ; => ((1 . 5) (3 . 4))
Note that setq
can be used to modify variables, not data structures, like pairs or lists.
Upvotes: 2