|
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