[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Why doesn't nconc change my variable?
From: |
Pascal J. Bourguignon |
Subject: |
Re: Why doesn't nconc change my variable? |
Date: |
Sun, 05 Oct 2014 20:04:49 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) |
Marcin Borkowski <mbork@wmi.amu.edu.pl> writes:
> Hi list,
>
> I don't get it.
>
> (setq my-list ())
> (nconc my-list '("wtf"))
>
> and my-list is still nil.
>
> If, OTOH, I do
>
> (setq my-list ())
> (setq my-list (nconc my-list '("wtf")))
Also, you are doing something dangerous here:
You are mixing mutable and immutable data.
This is dangerous, because now you may believe that your variable
contains mutable data, and try to mutate it, and you will actually try
to mutate immutable data, (which has usually strange or catastrophic
results).
(defvar my-list)
(setq my-list (list 1 2 3))
;; now, my-list contains mutable data. You can modify the car or
;; the cdr of any cell in the list.
(setq my-list (nconc my-list '("wtf")))
;; Now, my-list is bound to the list: (1 2 3 "wtf")
;; but this list is made of 3 mutable cons cells, and one immutable
;; cons cell, with one immutable string!
If you were to perform any of:
(setq my-list (nconc my-list '("bad")))
(setq my-list (car (last my-list) "bad"))
(setq (aref (car (last my-list)) 0) ?W)
(setq my-list (delete* "wtf" my-list :test (function string=)))
;; etc.
you would get strange/catastrophical results:
For example, try:
(defun strange (list)
(nconc list '("wtf")))
(let ((a (strange (list 1 2 3))))
(setf (car (last a)) "BAD")
(list a (strange (list 4 5 6))))
--> ((1 2 3 "BAD") (4 5 6 "BAD")) ; WTF, where is "wtf"?
If you try with:
(setf print-circle t)
(let ((a (strange (list 1 2 3))))
(setf (car (last a)) "strange")
(list a (strange (list 4 5 6))))
--> ((1 2 3 . #1=("strange")) (4 5 6 . #1#))
this may give you a hint of what's happening.
So avoid mixing mutable and immutable data, or consider the result to be
immutable (and therefore avoid using destructive operations on it).
Notice that append, while it copies the N-1 first arguments, it keeps
the last argument, so (append list '("wtf")) is no better
than (nconc list '("wtf")).
You need (nconc list (list 'wtf)) ; if you want immutable elements
or (nconc list (list (format "%s" "wtf"))) ; if you want
; mutable elements.
--
__Pascal Bourguignon__ http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
- Re: Why doesn't nconc change my variable?, (continued)
- Message not available
- Message not available
- Message not available
Re: Why doesn't nconc change my variable?, Pascal J. Bourguignon, 2014/10/04
Re: Why doesn't nconc change my variable?,
Pascal J. Bourguignon <=