ref: 23e857034070229923a7b3b800d608ab0e14236d
parent: 4679ff506c0070253da0d452b3fcfaf9bf047130
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Nov 3 02:34:28 EST 2024
length builtin: detect cycles and return infinity if there is any
--- a/builtins.c
+++ b/builtins.c
@@ -88,8 +88,21 @@
return fixnum(vector_size(a));
if(a == FL_NIL)
return fixnum(0);
- if(iscons(a))
- return fixnum(llength(a));
+ if(iscons(a)){
+ size_t n = 0;
+ value_t v = a, v2 = a;
+ do{
+ n++;
+ v = cdr_(v);
+ v2 = cdr_(v2);
+ if(iscons(v2))
+ v2 = cdr_(v2);
+ }while(iscons(v) && iscons(v2) && v != v2);
+ if(iscons(v2))
+ return mk_double(D_PINF);
+ n += llength(v);
+ return fixnum(n);
+ }
if(iscprim(a)){
cv = (cvalue_t*)ptr(a);
if(cp_class(cv) == bytetype)
--- a/test/unittest.lsp
+++ b/test/unittest.lsp
@@ -355,5 +355,9 @@
(assert (equal? (append '(1 2)) '(1 2)))
(assert (equal? (append '(1 2) '(3 4)) '(1 2 3 4)))
+(define a '(1))
+(set-cdr! a a)
+(assert (equal? (length a) +inf.0))
+
(princ "all tests pass\n")
#t