SRFI-1: Make `unfold' tail-recursive (fix bug #30071).
authorLudovic Courtès <ludo@gnu.org>
Fri, 8 Oct 2010 08:23:52 +0000 (10:23 +0200)
committerLudovic Courtès <ludo@gnu.org>
Fri, 8 Oct 2010 13:25:56 +0000 (15:25 +0200)
* module/srfi/srfi-1.scm (unfold): Make tail-recursive, following a
  suggestion by Szavai Gyula.

* test-suite/tests/srfi-1.test ("unfold"): New test prefix.

module/srfi/srfi-1.scm
test-suite/tests/srfi-1.test

index d7ef6bb..1e006c7 100644 (file)
@@ -454,11 +454,20 @@ that result.  See the manual for details."
        (apply kons (append! lists (list (f (map1 cdr lists)))))))))
 
 (define* (unfold p f g seed #:optional (tail-gen (lambda (x) '())))
-  (let uf ((seed seed))
+  (define (reverse+tail lst seed)
+    (let loop ((lst    lst)
+               (result (tail-gen seed)))
+      (if (null? lst)
+          result
+          (loop (cdr lst)
+                (cons (car lst) result)))))
+
+  (let loop ((seed   seed)
+             (result '()))
     (if (p seed)
-        (tail-gen seed)
-        (cons (f seed)
-              (uf (g seed))))))
+        (reverse+tail result seed)
+        (loop (g seed)
+              (cons (f seed) result)))))
 
 (define* (unfold-right p f g seed #:optional (tail '()))
   (let uf ((seed seed) (lis tail))
index ca34e8f..8569a3d 100644 (file)
             ;; lst unmodified
             (equal? '((1 2) (3 4) (5 6)) lst))))))
 
+;;
+;; unfold
+;;
+
+(with-test-prefix "unfold"
+
+  (pass-if "basic"
+    (equal? (iota 10)
+            (unfold (lambda (x) (>= x 10))
+                    identity
+                    1+
+                    0)))
+
+  (pass-if "tail-gen"
+    (equal? (append (iota 10) '(tail 10))
+            (unfold (lambda (x) (>= x 10))
+                    identity
+                    1+
+                    0
+                    (lambda (seed) (list 'tail seed)))))
+
+  (pass-if "tail-recursive"
+    ;; Bug #30071.
+    (pair? (unfold (lambda (x) (>= x 1e6))
+                   identity
+                   1+
+                   0))))
+
 ;;
 ;; length+
 ;;