ref: 7f39a68fac2376befd91c3a50e98339ef0ec6fd5
parent: 85672c88b534e613ab761628767c8d1c8be4ccdf
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
--
⑨