ldiff, tailp
ldiff, tailp Function
Syntax:
ldiff list object → result-list
tailp object list → generalized-boolean
Arguments and Values:
list—a list, which might be a dotted list.
object—an object.
result-list—a list.
generalized-boolean—a generalized boolean.
ldiff, tailpDescription:
If object is the same as some tail of list, tailp returns true; otherwise, it returns false.
If object is the same as some tail of list, ldiff returns a fresh list of the elements of list that precede object in the list structure of list; otherwise, it returns a copy2 of list.
Examples:
(let ((lists ’#((a b c) (a b c . d))))
(dotimes (i (length lists)) ()
(let ((list (aref lists i)))
(format t "~2&list=~S ~21T(tailp object list)~
~44T(ldiff list object)~%" list)
(let ((objects (vector list (cddr list) (copy-list (cddr list))
’(f g h) ’() ’d ’x)))
(dotimes (j (length objects)) ()
(let ((object (aref objects j)))
(format t "~& object=~S ~21T~S ~44T~S"
object (tailp object list) (ldiff list object))))))))
▷
▷ list=(A B C) (tailp object list) (ldiff list object)
▷ object=(A B C) T NIL
▷ object=(C) T (A B)
▷ object=(C) NIL (A B C)
▷ object=(F G H) NIL (A B C)
▷ object=NIL T (A B C)
▷ object=D NIL (A B C)
▷ object=X NIL (A B C)
▷
▷ list=(A B C . D) (tailp object list) (ldiff list object)
▷ object=(A B C . D) T NIL
▷ object=(C . D) T (A B)
▷ object=(C . D) NIL (A B C . D)
▷ object=(F G H) NIL (A B C . D)
▷ object=NIL NIL (A B C . D)
▷ object=D T (A B C)
▷ object=X NIL (A B C . D)
→ NIL
Side Effects:
Neither ldiff nor tailp modifies either of its arguments.
Exceptional Situations:
Should be prepared to signal an error of type type-error if list is not a proper list or a dotted list.
See Also:
set-differenceNotes:
If the list is a circular list, tailp will reliably yield a value only if the given object is in fact a tail of list. Otherwise, the consequences are unspecified: a given implementation which detects the circularity must return false, but since an implementation is not obliged to detect such a situation, tailp might just loop indefinitely without returning in that case.
tailp could be defined as follows:
(defun tailp (object list)
(do ((list list (cdr list)))
((atom list) (eql list object))
(if (eql object list)
(return t))))
and ldiff could be defined by:
(defun ldiff (list object)
(do ((list list (cdr list))
(r ’() (cons (car list) r)))
((atom list)
(if (eql list object) (nreverse r) (nreconc r list)))
(when (eql object list)
(return (nreverse r)))))
Expanded Reference: ldiff, tailp
Basic tailp usage
tailp returns true if the object is eq to some tail (including the list itself and the terminating atom) of the list.
(let* ((lst '(a b c d))
(tail (cddr lst))) ; tail is (c d)
(tailp tail lst))
=> T
(tailp '(c d) '(a b c d))
=> NIL
NIL is a tail of every proper list
(tailp nil '(a b c))
=> T
(tailp nil '())
=> T
Basic ldiff usage
ldiff returns a fresh list of elements that precede the given tail in the list. If the object is not a tail, it returns a copy of the entire list.
(let* ((lst '(1 2 3 4 5))
(tail (cdddr lst))) ; tail is (4 5)
(ldiff lst tail))
=> (1 2 3)
ldiff with a non-tail object
When the object is not a tail, ldiff returns a copy of the whole list.
(ldiff '(a b c) '(not a tail))
=> (A B C)
(ldiff '(a b c) 'x)
=> (A B C)
Splitting a list at a known position
ldiff and tailp work together for splitting a list at a cons cell.
(let* ((lst '(a b c d e))
(split-point (member 'c lst)))
(values (ldiff lst split-point) split-point))
=> (A B)
=> (C D E)
Dotted lists
tailp can also check tails of dotted lists, including the terminating atom.
(let ((lst '(a b . c)))
(values (tailp 'c lst)
(tailp nil lst)))
=> T
=> NIL