@end deffn
@deffn {SRFI 1 procedure} length+ clist
-@var{Clist} must be a proper, dotted, or circular list. If
-@var{clist} is a circular list, returns @code{#f}, otherwise returns
-the number of pairs comprising the list (which is the same as the
-length for a proper list).
+@var{Clist} must be a proper or circular list. If @var{clist} is a
+circular list, returns @code{#f}, otherwise returns the number of
+pairs comprising the list (which is the same as the length for a
+proper list).
@example
@group
(length+ (list 'a 'b 'c)) @result{} 3
-(length+ (cons* 'a 'b 'c)) @result{} 2
+(length+ (cons* 'a 'b 'c)) @error{}
(length+ (circular-list 'a 'b 'c)) @result{} #f
@end group
@end example
@end deffn
+@deffn procedure count-pairs object
+Counts the number of pairs in a list-like @var{object}. If
+@var{object} is a proper list, returns the same value as
+@code{length}. If @var{object} is a dotted list, returns the number
+of pairs including the last one. If @var{object} is a circular list,
+counts the number of pairs up to and including the one with the
+backwards link. If @var{object} is any other object, returns @code{0}
+as apropriate for an empty dotted list.
+
+@example
+@group
+(count-pairs (list 'a 'b 'c)) @result{} 3
+(count-pairs (cons* 'a 'b 'c)) @result{} 2
+(count-pairs (circular-list 'a 'b 'c)) @result{} 3
+@end group
+@end example
+@end deffn
+
@deffn {standard procedure} null? object
@cindex type predicate, for empty list
@cindex empty list, predicate for
(and (null? l1)
length))))
+(define (count-pairs x)
+
+ (define (loop x lag n)
+ (if (pair? x)
+ (let ((x (cdr x))
+ (n (fix:+ n 1)))
+ (if (pair? x)
+ (let ((x (cdr x))
+ (lag (cdr lag))
+ (n (fix:+ n 1)))
+ (if (eq? x lag)
+ (count-pairs-in-cycle)
+ (loop x lag n)))
+ n))
+ n))
+
+ ;; Deferred to avoid overhead on non-cyclical inputs.
+ (define (count-pairs-in-cycle)
+ (let ((ht (make-hash-table eq-comparator)))
+ (let loop ((x x) (n 0))
+ (if (hash-table-contains? ht x)
+ n
+ (begin
+ (hash-table-set! ht x #t)
+ (loop (cdr x) (fix:+ n 1)))))))
+
+ (loop x x 0))
+\f
(define (length=? left right)
(define (%length=? n list)
(cond ((pair? list) (and (fix:positive? n)