Akasha
Akasha

Reputation: 235

Why is setq not doing anything?

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

Answers (3)

Rainer Joswig
Rainer Joswig

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

Will Ness
Will Ness

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

Renzo
Renzo

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

Related Questions