endp
endp Function
Syntax:
endp list → generalized-boolean
Arguments and Values:
list—a list, which might be a dotted list or a circular list.
generalized-boolean—a generalized boolean.
Description:
Returns true if list is the empty list. Returns false if list is a cons.
Examples:
(endp nil) → true
(endp ’(1 2)) → false
(endp (cddr ’(1 2))) → true
Exceptional Situations:
Should signal an error of type type-error if list is not a list.
Notes:
The purpose of endp is to test for the end of proper list. Since endp does not descend into a cons, it is well-defined to pass it a dotted list. However, if shorter “lists” are iteratively produced by calling cdr on such a dotted list and those “lists” are tested with endp, a situation that has undefined consequences will eventually result when the non-nil atom (which is not in fact a list) finally becomes the argument to endp. Since this is the usual way in which endp is used, it is conservative programming style and consistent with the intent of endp to treat endp as simply a function on proper lists which happens not to enforce an argument type of proper list except when the argument is atomic.
Expanded Reference: endp
Testing for end of a proper list
endp returns true when given NIL (the empty list) and false when given a cons. It is designed for testing termination when iterating over a proper list.
(endp nil)
=> T
(endp '(a b c))
=> NIL
Traversing a list with endp
endp is the preferred predicate for testing list termination in loops and recursive functions, because it signals an error if it encounters a non-list atom (unlike null).
(let ((lst '(10 20 30))
(sum 0))
(do ((tail lst (cdr tail)))
((endp tail) sum)
(incf sum (car tail))))
=> 60
endp checks that the argument is a list
Unlike null, endp should signal a type-error if given something that is neither NIL nor a cons. This makes it a safer choice for iterating proper lists.
(endp '())
=> T
(endp '(x))
=> NIL
;; (endp 42) would signal a TYPE-ERROR
Using endp in recursive list processing
endp works well as the base case check in recursive functions that consume proper lists.
(defun sum-list (lst)
(if (endp lst)
0
(+ (car lst) (sum-list (cdr lst)))))
(sum-list '(1 2 3 4 5))
=> 15
(sum-list '())
=> 0
endp with cddr for pairwise processing
When processing list elements in pairs, endp can test the remaining tail at each step.
(defun pairwise-max (lst)
"Return a list of the max of each consecutive pair."
(if (endp (cdr lst))
nil
(cons (max (first lst) (second lst))
(pairwise-max (cddr lst)))))
(pairwise-max '(3 7 2 9 5 1))
=> (7 9 5)