[Date Prev][Date Next][Thread Prev][][Date Index][Thread Index]

Re: reversed and copied lists



On 2019-02-18 05:27, Boruch Baum wrote:
> I decided to scan the code for unnecessary nreverse operations, and

...

> The function in question is:
>
> (defun w3m-sub-list (list n)

...

> What's bothering me is the documentation for function copy-sequence
> which seems unclear to me whether it really is creating a copy or just
> another symbol pointing to the same objects.
>
>   "Return a copy... are not copied; they are shared...
>    may return the same empty object instead of its copy"
>
> So I tried a few attempts at destructive tests:
>
> (let ((this '(a b c d e f g)) that)
>   (setq that
>     (prog1
>       (last this 12)
>       (setq this nil)))
>   (setq this "aa")
>   that)
> (let ((this '(a b c d e f g)) that)
>   (setq that
>     (prog1
>       (copy-sequence this)
>       (setq this nil)))
>   (push "aa" this)
>   that)
>
> And some attempts at destructive tests, using w3m-sub-list:
>
> (let ((this '(a b c d e f g)) that)
>   (setq that (w3m-sub-list this 4))
>   (setq this nil)
>   that)
> (let ((this '(a b c d e f g)) that)
>   (prog1
>     (setq that (w3m-sub-list this 4))
>     (setq this nil)))

The problem with those tests were that they were just manipulating the
pointers to the head of the list(s). Compare with the following, which
shows that function copy-sequence really is making a copy.

(let ((this '(a b c d e f g)) that)
  (setq that (last this 12))
  (setf (nth 2 this) "XXX")
  (message "this: %s  that: %s\n" this that))

(let ((this '(a b c d e f g)) that)
  (setq that (butlast this -12))
  (setf (nth 2 this) "XXX")
  (message "this: %s  that: %s\n" this that))

(let ((this '(a b c d e f g)) that)
  (setq that (copy-sequence this))
  (setf (nth 2 this) "XXX")
  (message "this: %s  that: %s\n" this that))

(let ((this '(a b c d e f g)) that)
  (setq that (w3m-sub-list this 5))
  (setf (nth 2 this) "XXX")
  (message "this: %s  that: %s\n" this that))

(let ((this '(a b c d e f g)) that)
  (setq that (w3m-sub-list this 12))
  (setf (nth 2 this) "XXX")
  (message "this: %s  that: %s\n" this that))

So a better resolution (returning nil for n=0) would be:

(defun w3m-sub-list (list n)
  "Return a list of the first N elements of LIST.
If N is negative, return a list of the last N elements of LIST."
  (copy-sequence
    (if (integerp n)
      (cond
       ((< n 0)
         (last list (- n)))
       ((> n 0)
         (butlast list (- (length list) n)))
       (t nil)) ; (= n 0)
     list)))

-- 
hkp://keys.gnupg.net
CA45 09B5 5351 7C11 A9D1  7286 0036 9E45 1595 8BC0