~ 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