Left folds Bradley Lucier (17 Sep 2022 22:18 UTC)
|
||
Re: Left folds
Marc Nieper-Wißkirchen
(18 Sep 2022 08:44 UTC)
|
||
(missing)
|
||
(missing)
|
||
Re: Left folds
Bradley Lucier
(20 Sep 2022 14:15 UTC)
|
||
Re: Left folds
Marc Nieper-Wißkirchen
(20 Sep 2022 14:25 UTC)
|
||
Re: Left folds
Marc Nieper-Wißkirchen
(22 Sep 2022 20:52 UTC)
|
||
Re: Left folds
Lucier, Bradley J
(22 Sep 2022 21:14 UTC)
|
||
Re: Left folds
Marc Nieper-Wißkirchen
(23 Sep 2022 09:25 UTC)
|
||
Re: Left folds
John Cowan
(23 Sep 2022 17:22 UTC)
|
||
Re: Left folds
Marc Nieper-Wißkirchen
(23 Sep 2022 17:30 UTC)
|
||
Re: Left folds
Bradley Lucier
(23 Sep 2022 18:39 UTC)
|
||
Re: Left folds
Bradley Lucier
(24 Sep 2022 00:12 UTC)
|
||
Re: Left folds
Arthur A. Gleckler
(24 Sep 2022 00:24 UTC)
|
||
Fwd: Left folds
Marc Nieper-Wißkirchen
(20 Sep 2022 14:17 UTC)
|
||
Re: Left folds
John Cowan
(18 Sep 2022 10:41 UTC)
|
||
Re: Left folds
Marc Nieper-Wißkirchen
(18 Sep 2022 13:29 UTC)
|
||
Re: Left folds
Bradley Lucier
(20 Sep 2022 00:32 UTC)
|
The documentation for array-foldl says Then conceptually |(array-foldl operator identity array . arrays)| returns |(apply foldl operator identity (array->list (apply array-map list array arrays)))| Right now, that's not quite true for generalized arrays. The documentation implies that all array elements are evaluated before the fold is begun, but an expansion of the code for two dimensions is (let ((upper-1 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 4 '#<type #3 %%interval> %%interval-upper-bounds) 1)) (upper-0 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 4 '#<type #3 %%interval> %%interval-upper-bounds) 0)) (lower-1 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 3 '#<type #3 %%interval> %%interval-lower-bounds) 1)) (lower-0 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 3 '#<type #3 %%interval> %%interval-lower-bounds) 0))) (letrec ((loop-0 (lambda (f operator upper-1 upper-0 lower-1 i_0 result) (if ('#<procedure #31 ##fx=> i_0 upper-0) result (letrec ((loop-1 (lambda (f operator upper-1 upper-0 lower-1 i_0 i_1 result) (if ('#<procedure #31 ##fx=> i_1 upper-1) (loop-0 f operator upper-1 upper-0 lower-1 ('#<procedure #39 ##fx+> i_0 1) result) (loop-1 f operator upper-1 upper-0 lower-1 i_0 ('#<procedure #39 ##fx+> i_1 1) (operator result (f i_0 i_1))))))) ;; <<<<<<< HERE (loop-1 f operator upper-1 upper-0 lower-1 i_0 lower-1 result)))))) (loop-0 f operator upper-1 upper-0 lower-1 lower-0 identity))) So we intersperse evaluations of the "combining" operator (named operator) with evaluation of the array-getter (here named f) at the place marked HERE. With call/cc and some set!'s one could probably detect the difference. If the user wants to play call/cc games with operator, then I don't see how we can stop her, or why we would want to, but should we evaluate array-getter at all multi-indices before starting to combine things with operator, as the documentation implies? The code for array-foldr does evaluate array-getter at all multi-indices before combining results with operator: (let ((upper-1 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 4 '#<type #3 %%interval> %%interval-upper-bounds) 1)) (upper-0 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 4 '#<type #3 %%interval> %%interval-upper-bounds) 0)) (lower-1 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 3 '#<type #3 %%interval> %%interval-lower-bounds) 1)) (lower-0 ('#<procedure #17 ##vector-ref> ('#<procedure #5 ##unchecked-structure-ref> interval 3 '#<type #3 %%interval> %%interval-lower-bounds) 0))) (letrec ((loop-0 (lambda (f operator identity upper-1 upper-0 lower-1 i_0) (if ('#<procedure #31 ##fx=> i_0 upper-0) identity (letrec ((loop-1 (lambda (f operator identity upper-1 upper-0 lower-1 i_0 i_1) (if ('#<procedure #31 ##fx=> i_1 upper-1) (loop-0 f operator identity upper-1 upper-0 lower-1 ('#<procedure #39 ##fx+> i_0 1)) (let ((item (f i_0 i_1))) (let ((result (loop-1 f operator identity upper-1 upper-0 lower-1 i_0 ('#<procedure #39 ##fx+> i_1 1)))) (operator item result))))))) (loop-1 f operator identity upper-1 upper-0 lower-1 i_0 lower-1)))))) (loop-0 f operator identity upper-1 upper-0 lower-1 lower-0))) But you can see that with lambda-lifting, 9 words (8 arguments plus the return label) are pushed to the stack for each array item iteration. Brad