[alexandria-devel] Re: length=1

Tobias C. Rittweiler tcr at freebits.de
Sat Feb 23 10:52:47 UTC 2008


"Attila Lendvai" <attila.lendvai at gmail.com> writes:

> dear list,
>
> is there any objections against this?
>
> (declaim (inline length=1))
>
> (defun length=1 (sequence)
>   (if (listp sequence)
>       (and sequence
>            (null (rest sequence)))
>       (= 1 (length sequence))))
>
> in optimized code, where type information is available, it drops the
> type check. and otherwise it works for sequences and is fast for
> lists.
>
> maybe it could be extended into two functions: length= and length=1,
> where length= optimizes for lists using nthcdr.

Yes, I favor such an inclusion. I also vote for including a LENGTH>.
I've appended the definitions that I use personally below my
email. 

There's a compiler macro for LENGTH= for when it's called with either 1
or 2, as these are the numeric arguments I've found myself to use most
often.

Exporting LENGTH=1 and LENGTH=2 may be debateable, the only use case is
the one Andreas Fuchs mentioned, i.e. as arguments to FIND-IF &c.

  -T.


(export '(length= length> length=1 length=2))

(defmacro optimizing-length (inline-p &body body)
  `(locally (declare (optimize speed) (inline length))
     , at body))

(defun length= (seq n)
  "Test for whether SEQ contains N number of elements. I.e. it's equivalent
 to (= (LENGTH SEQ) N), but besides being more concise, it may also be more
 efficiently implemented."
  (check-type n integer)
  (typecase seq 
    (list (do ((i n (1- i))
               (list seq (cdr list)))
              ((or (<= i 0) (null list))
               (and (zerop i) (null list)))))
    (simple-vector (optimizing-length (= n (length seq))))
    (vector        (optimizing-length (= n (length seq))))
    (sequence      (optimizing-length (= n (length seq))))))

(define-compiler-macro length= (&whole form sequence n)
  (cond ((eql n 1) `(length=1 ,sequence))
	((eql n 2) `(length=2 ,sequence))      
	(t form)))

(defun length> (seq n)
  "Returns non-nil if (> (length LIST) N)."
  (check-type n integer)
  (etypecase seq
    (list          (and (>= n 0) (nthcdr n seq) t))
    (simple-vector (optimizing-length (> (length seq) n)))
    (vector        (optimizing-length (> (length seq) n)))
    (sequence      (optimizing-length (> (length seq) n)))))

(defun length=1 (sequence)
  (declare (optimize speed))
  (declare (inline length))
  (typecase sequence
    (list          (and sequence (null (rest sequence))))
    (simple-vector (= 1 (length sequence)))
    (vector        (= 1 (length sequence)))
    (sequence      (= 1 (length sequence)))))

(defun length=2 (sequence)
  (declare (optimize speed))
  (declare (inline length))
  (typecase sequence
    (list          (and sequence (cdr sequence) (null (cddr sequence))))
    (simple-vector (= 2 (length sequence)))
    (vector        (= 2 (length sequence)))
    (sequence      (= 2 (length sequence)))))





More information about the alexandria-devel mailing list