help-gnu-emacs
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]