How to reset the value of associate list element
How to reset the value of associate list element
If I have a associate list ((:a a) (:b b) (:c c)), how can I set b to (:b z)?
Can you tell me different ways to do it?
Thanks!!
Can you tell me different ways to do it?
Thanks!!
Re: How to reset the value of associate list element
Not knowing the answer myself, I figured out the easy way.joybee wrote:If I have a associate list ((:a a) (:b b) (:c c)), how can I set b to (:b z)?
Can you tell me different ways to do it?
Thanks!!
Code: Select all
(let ((lst '((:a a) (:b b) (:c c))))
(setf (car (cdr (car (cdr lst)))) 'z) ;abra-cadadr!
lst)
Edit: Also, SBCL is yelling at me about "constant data" for some reason.
Edit again: This is fine, oddly enough:
Code: Select all
(let ((lst (list '(a a) '(b b) '(c c))))
(rplacd (assoc 'b lst) 'z))
"If you want to improve, be content to be thought foolish and stupid." -Epictetus
Re: How to reset the value of associate list element
Code: Select all
(car (cdr (car (cdr <list>)))) => (cadadr <list>)
Code: Select all
(rplacd (assoc <key> <a-list>) <new-value>)
Re: How to reset the value of associate list element
Not quite. LIST is a function which creates a list at runtime, whereas QUOTE is a special operator which creates a list at compile time. Quoted forms are treated as source literals, and modifying them has an unspecified behaviour, which in principle might include a memory protection fault if they are placed in read-only memory. I don't think any implementation actually does that, but modifying literals is usually not a good idea.Duke wrote:Yet the list form and the quoted form evaluate to the same thing.
Re: How to reset the value of associate list element
Thanks, everyone!
Here is a little example I ran on sbcl.
* (equal (list 1 2) (rplacd (list 1 1) 2))
* NIL
* (rplacd (list 1 1) 2)
* (1 . 2)
What I want is after value reset the evaluation of equal returns T. How can I achive that?
Here is a little example I ran on sbcl.
* (equal (list 1 2) (rplacd (list 1 1) 2))
* NIL
* (rplacd (list 1 1) 2)
* (1 . 2)
What I want is after value reset the evaluation of equal returns T. How can I achive that?
Re: How to reset the value of associate list element
I see. I guess I should have read the documentation on QUOTE while I was at it.Ramarren wrote:Not quite. LIST is a function which creates a list at runtime, whereas QUOTE is a special operator which creates a list at compile time. Quoted forms are treated as source literals, and modifying them has an unspecified behaviour, which in principle might include a memory protection fault if they are placed in read-only memory. I don't think any implementation actually does that, but modifying literals is usually not a good idea.

Thanks.
You notice that rplacd returns a dotted pair? That's a cons, which is distinct from a list. Putting it simply, a list is a set of conses with a NIL on the end, like this:joybee wrote:Thanks, everyone!
Here is a little example I ran on sbcl.
* (equal (list 1 2) (rplacd (list 1 1) 2))
* NIL
* (rplacd (list 1 1) 2)
* (1 . 2)
What I want is after value reset the evaluation of equal returns T. How can I achive that?
Code: Select all
(rplacd (list 1 1) 2) => (1 . 2)
(list 1 2) => (1 . (2 . nil))
Code: Select all
(equal (cons 1 (cons 2 nil)) (list 1 2)) => T
(equal (cons 1 2) (rplacd (list 1 1) 2)) => T
"If you want to improve, be content to be thought foolish and stupid." -Epictetus
Re: How to reset the value of associate list element
You notice that rplacd returns a dotted pair? That's a cons, which is distinct from a list. Putting it simply, a list is a set of conses with a NIL on the end, like this:Duke wrote:I see. I guess I should have read the documentation on QUOTE while I was at it.Ramarren wrote:Not quite. LIST is a function which creates a list at runtime, whereas QUOTE is a special operator which creates a list at compile time. Quoted forms are treated as source literals, and modifying them has an unspecified behaviour, which in principle might include a memory protection fault if they are placed in read-only memory. I don't think any implementation actually does that, but modifying literals is usually not a good idea.
Thanks.
joybee wrote:Thanks, everyone!
Here is a little example I ran on sbcl.
* (equal (list 1 2) (rplacd (list 1 1) 2))
* NIL
* (rplacd (list 1 1) 2)
* (1 . 2)
What I want is after value reset the evaluation of equal returns T. How can I achive that?
Code: Select all
(rplacd (list 1 1) 2) => (1 . 2)
(list 1 2) => (1 . (2 . nil))
Code: Select all
(cons 1 (cons 2 nil))
Code: Select all
(equal (cons 1 2) (rplacd (list 1 1) 2)) => T
"If you want to improve, be content to be thought foolish and stupid." -Epictetus
Re: How to reset the value of associate list element
The particular problem here is that an association list usually is a list of dotted pairs like this:
This means that the last element in each cell is a symbol and not NIL, like in a normal (non-dotted) list. 'assoc' works with normal list as well as with dotted lists, but 'rplaca' expects a cons (a dotted pair) and not a normal list.
If you want to use a normal list instead of a dotted list as an association list (what is not a really good idea btw.), then there is no other way than to use 'setf' together with 'second' to replace the second element in a cell like this:
But using normal lists as association list is quite non-standard Common Lisp.
You can create a dotted association list by using 'cons' like this:
Now also all the code from above works:
Code: Select all
((:a . a) (:b . b) (:c . c))
If you want to use a normal list instead of a dotted list as an association list (what is not a really good idea btw.), then there is no other way than to use 'setf' together with 'second' to replace the second element in a cell like this:
Code: Select all
(let ((lst (list (list :a 'a) (list :b 'b) (list :c 'c))))
(setf (second (assoc :b lst)) 'z)
lst)
=> ((:A A) (:B Z) (:C C))
You can create a dotted association list by using 'cons' like this:
Code: Select all
(list (cons :a 'a) (cons :b 'b) (cons :c 'c))
=> ((:A . A) (:B . B) (:C . C))
Code: Select all
(let ((lst (list (cons :a 'a) (cons :b 'b) (cons :c 'c))))
(rplacd (assoc :b lst) 'z)
lst)
=> ((:A . A) (:B . Z) (:C . C))
(equal (cons 1 2) (rplacd (cons 1 1) 2))
=> T
(rplacd (cons 1 1) 2)
=> (1 . 2)
-
- Posts: 447
- Joined: Sat Jun 28, 2008 7:49 am
- Location: Austin, TX
- Contact:
Re: How to reset the value of associate list element
To be a bit more specific, QUOTE is a special operator, but it merely marks the form that follows it (either an atom or a list) in the source code as being a literal, rather than a form that should be further evaluated (function, macro, or variable reference). But you can, for instance, build up a form that includes QUOTE using LIST, CONS, and other functions and then feed that to EVAL and the right things will occur. But you are correct even in that case that QUOTE marks portions of the source code sexpr as being literal values, which should not be modified because that could actually lead to modification of the source sexpr.Ramarren wrote:Not quite. LIST is a function which creates a list at runtime, whereas QUOTE is a special operator which creates a list at compile time. Quoted forms are treated as source literals, and modifying them has an unspecified behaviour, which in principle might include a memory protection fault if they are placed in read-only memory. I don't think any implementation actually does that, but modifying literals is usually not a good idea.Duke wrote:Yet the list form and the quoted form evaluate to the same thing.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
-
- Posts: 406
- Joined: Sat Mar 07, 2009 6:17 pm
- Location: Brazil
- Contact:
Re: How to reset the value of associate list element
Just to exemplify what findinglisp said:
You need to be careful not to modify any list created by quote, or, even better, not to create any list with quote unless you are sure it is always gonna be treated as constant data.
Code: Select all
CL-USER> (defun literal ()
(quote (1 2 3)))
LITERAL
CL-USER> (defun constructed ()
(list 1 2 3))
CONSTRUCTED
CL-USER> (eq (literal) (literal))
T
CL-USER> (eq (constructed) (constructed))
NIL
CL-USER> (setf (cadr (literal)) 50)
50
CL-USER> (literal)
(1 50 3)
CL-USER> (setf (cadr (constructed)) 50)
50
CL-USER> (constructed)
(1 2 3)