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

reversed and copied lists



I decided to scan the code for unnecessary nreverse operations, and came
acrosss a situation that looks ripe for taking an axe to, but I wasn't
sure if there wasn't some subtle lisp consequence that I was missing.
Even after performing some tests, I'm still not confident in myself, so
I thought to share it on the list for feedback, and maybe improve my
lisp abilities.

The function in question is:

(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."
  (if (integerp n)
      (if (< n 0)
	  ;; N is negative, extract the last items
	  (if (>= (- n) (length list))
	      (copy-sequence list)
	    (nthcdr (+ (length list) n) (copy-sequence list)))
	;; N is positive, extract the first items
	(if (>= n (length list))
	    (copy-sequence list)
	  (nreverse (nthcdr (- (length list) n) (reverse list)))))
    (copy-sequence list)))

What seems to me more sensible is:

(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."
  (if (integerp n)
    (cond
     ((< n 0)
       (last list (- n)))
     ((> n 0)
       (butlast list (- (length list) n)))
     (t list))
   list))

Here are some basic tests:

  (w3m-sub-list '(a b c d e f g) 4)
  (w3m-sub-list '(a b c d e f g) -4)
  (w3m-sub-list '(a b c d e f g) t)
  (w3m-sub-list '(a b c d e f g) nil)
  (w3m-sub-list '(a b c d e f g) 12)
  (w3m-sub-list '(a b c d e f g) -12)

BTW, there's a bug in the original version when n=0
  (w3m-sub-list '(a b c d e f g) 0)

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)))

In any case, there is the n=0 bug to address.

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