リストの要素数を取得する - lisp-cookbook-ja/common-lisp GitHub Wiki

リスト

リストの長さは length 関数で調べることができます。

(length '(1 2 3 4)) ;=> 4

ただし、リストの構造を調べるような場合には length を使うよりも car, cdr, null を使って構造を調べた方が効率がよいです。例えばリストが if フォームとして適正な形をしているか調べる関数を考えます。

(defun if? (xs)
  (and (<= 3 (length xs) 4)
       (eql (car xs) 'if)))

この場合、length で長さを調べると、引数で与えられたリストの長さが大きい場合、余計な時間がかかってしまいます。

(defun if? (xs)
  (and (consp xs)
       (eql (car xs) 'if)
       (not (null (cdr xs)))
       (not (null (cddr xs)))
       (or (null (cdddr xs))
           (null (cddddr xs)))))

とすれば引数のリストの長さにかかわらず定数時間で計算が終了します。

同じ理由で、リストが空かどうか調べるには length を使うよりも null を使う方が良いでしょう。

;; fast version
(null (make-list 5000000 0)) ;=> nil

;; slow version
(zerop (length (make-list 5000000))) ;=> nil

同様のアイディアとして、Paul Graham著のOn Lispにsingleという例があります。 要素が1つならば真を返しますが、長さではなく、1つ目の要素の後が終端(nil)かどうかを判定しています。

(defun single (lst)
  (and (consp lst) (not (cdr lst))))