~ chicken-core (chicken-5) 0fc30833918e25090f5e7da0911cf970f21a13a1


commit 0fc30833918e25090f5e7da0911cf970f21a13a1
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Sat Jul 2 23:04:02 2011 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Sat Jul 2 23:04:02 2011 +0200

    added foldl and foldr

diff --git a/c-platform.scm b/c-platform.scm
index bd6f4605..6c76d94a 100644
--- a/c-platform.scm
+++ b/c-platform.scm
@@ -146,6 +146,7 @@
     block-ref block-set! number-of-slots substring-index substring-index-ci
     hash-table-ref any? read-string substring=? substring-ci=?
     first second third fourth make-record-instance
+    foldl foldr
     u8vector-length s8vector-length u16vector-length s16vector-length u32vector-length s32vector-length
     f32vector-length f64vector-length setter
     u8vector-ref s8vector-ref u16vector-ref s16vector-ref u32vector-ref s32vector-ref
diff --git a/chicken.import.scm b/chicken.import.scm
index 2a294282..f3a88efb 100644
--- a/chicken.import.scm
+++ b/chicken.import.scm
@@ -93,6 +93,8 @@
    flonum-radix
    flonum?
    flush-output
+   foldl
+   foldr
    force-finalizers
    fp-
    fp*
diff --git a/compiler-syntax.scm b/compiler-syntax.scm
index eec4f7e6..67a919e2 100644
--- a/compiler-syntax.scm
+++ b/compiler-syntax.scm
@@ -133,7 +133,7 @@
   (if (and (fx> (length x) 1)
 	   (memq 'o extended-bindings) ) ; s.a.
       (let ((%tmp (r 'tmp)))
-	`(,(r 'lambda) (,%tmp) ,(fold-right list %tmp (cdr x))))
+	`(,(r 'lambda) (,%tmp) ,(fold-right list %tmp (cdr x)))) ;XXX use foldr
       x))
 
 (define-internal-compiler-syntax ((sprintf #%sprintf format #%format) x r c)
@@ -253,3 +253,51 @@
 				      (fail #t "illegal format-string character `~c'" dchar) ) ) )
 			       (loop '()) )
 			     (loop (cons c chunk)))))))))))))
+
+(define-internal-compiler-syntax ((foldr #%foldr) x r c)
+  (pair?)
+  (if (and (fx= (length x) 4)
+	   (memq 'foldr extended-bindings) ) ; s.a.
+      (let ((f (cadr x))
+	    (z (caddr x))
+	    (lst (cadddr x))
+	    (%let* (r 'let*))
+	    (%let (r 'let))
+	    (%pair? (r 'pair?))
+	    (%if (r 'if))
+	    (loopvar (gensym "foldr"))
+	    (lstvar (gensym)))
+	`(,%let* ((,lstvar ,lst))
+		 (##core#check (##sys#check-list ,lstvar (##core#quote foldr)))
+		 (,%let ,loopvar ((,lstvar ,lstvar))
+			(,%if (,%pair? ,lstvar)
+			      (,f (##sys#slot ,lstvar 0) 
+				     (##core#app ,loopvar (##sys#slot ,lstvar 1)))
+			      ,z))))
+      x))
+
+(define-internal-compiler-syntax ((foldl #%foldl) x r c) 
+  (pair?)
+  (if (and (fx= (length x) 4)
+	   (memq 'foldl extended-bindings) ) ; s.a.
+      (let ((f (cadr x))
+	    (z (caddr x))
+	    (lst (cadddr x))
+	    (%let* (r 'let*))
+	    (%let (r 'let))
+	    (%if (r 'if))
+	    (%pair? (r 'pair?))
+	    (zvar (gensym))
+	    (loopvar (gensym "foldl"))
+	    (lstvar (gensym)))
+	`(,%let* ((,zvar ,z)
+		  (,lstvar ,lst))
+		 (##core#check (##sys#check-list ,lstvar (##core#quote foldl)))
+		 (,%let ,loopvar ((,lstvar ,lstvar) (,zvar ,zvar))
+			(,%if (,%pair? ,lstvar)
+			      (##core#app 
+			       ,loopvar
+			       (##sys#slot ,lstvar 1) 
+			       (,f ,zvar (##sys#slot ,lstvar 0)))
+			      ,zvar))))
+      x))
diff --git a/library.scm b/library.scm
index 4e8a538f..c6ed34b7 100644
--- a/library.scm
+++ b/library.scm
@@ -4874,3 +4874,20 @@ EOF
 
 (define ##sys#dump-heap-state (##core#primitive "C_dump_heap_state"))
 (define ##sys#filter-heap-objects (##core#primitive "C_filter_heap_objects"))
+
+
+;;; fast folds with correct argument order
+
+(define (foldl f z lst)
+  (##sys#check-list lst 'foldl)
+  (let loop ((lst lst) (z z))
+    (if (not (pair? lst))
+	z
+	(loop (##sys#slot lst 1) (f z (##sys#slot lst 0))))))
+
+(define (foldr f z lst)
+  (##sys#check-list lst 'foldr)
+  (let loop ((lst lst))
+    (if (not (pair? lst))
+	z
+	(f (##sys#slot lst 0) (loop (##sys#slot lst 1))))))
diff --git a/manual/Unit library b/manual/Unit library
index fd4158e0..b200fff3 100644
--- a/manual/Unit library	
+++ b/manual/Unit library	
@@ -913,6 +913,33 @@ Returns {{#t}} if the two argument blobs are of the same
 size and have the same content.
 
 
+=== Lists
+
+==== foldl
+
+<procedure>(foldl PROCEDURE INIT LIST)</procedure>
+
+Applies {{PROCEDURE}} to the elements from {{LIST}}, beginning from the left:
+
+<enscript hightlight=scheme>
+(foldl + 0 '(1 2 3))    ==>    (+ (+ (+ 0 1) 2) 3)
+</enscript>
+
+Note that the order of arguments taken by {{PROCEDURE}} is different
+from the {{SRFI-1}} {{fold}} procedure, but matches the more intuitive
+order used in Haskell.
+
+
+==== foldr
+
+<procedure>(foldr PROCEDURE INIT LIST)</procedure>
+
+Applies {{PROCEDURE}} to the elements from {{LIST}}, beginning from the right:
+
+<enscript hightlight=scheme>
+(foldr + 0 '(1 2 3))    ==>    (+ 1 (+ 2 (+ 3 0)))
+</enscript>
+
 
 === Vectors
 
diff --git a/manual/faq b/manual/faq
index ca26480d..b471871b 100644
--- a/manual/faq
+++ b/manual/faq
@@ -473,6 +473,7 @@ The following extended bindings are handled specially:
 {{cpu-time}} {{error}} {{call/cc}} {{any?}}
 {{substring=?}} {{substring-ci=?}} {{substring-index}} {{substring-index-ci}}
 {{printf}} {{sprintf}} {{fprintf}} {{format}} {{o}}
+{{foldl}} {{foldr}}
 
 ==== What's the difference betweem "block" and "local" mode?
 
Trap