mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-01 20:30:28 +02:00
More of:
(SRFI-1 Fold and Map): Rewrite fold, pair-fold and reduce for clarity.
This commit is contained in:
parent
ad3d5a65c8
commit
5f708db610
1 changed files with 33 additions and 54 deletions
|
@ -522,9 +522,9 @@ elements from a list,
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Clearly the same sort of thing can be done with a @code{for-each} and
|
Clearly the same sort of thing can be done with a @code{for-each} and
|
||||||
a variable in which build the result, but a self-contained @var{proc}
|
a variable in which to build the result, but a self-contained
|
||||||
can be re-used in multiple contexts, where a @code{for-each} would
|
@var{proc} can be re-used in multiple contexts, where a
|
||||||
have to be written out each time.
|
@code{for-each} would have to be written out each time.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} pair-fold proc init lst1 @dots{} lstN
|
@deffn {Scheme Procedure} pair-fold proc init lst1 @dots{} lstN
|
||||||
|
@ -533,68 +533,47 @@ The same as @code{fold} and @code{fold-right}, but apply @var{proc} to
|
||||||
the pairs of the lists instead of the list elements.
|
the pairs of the lists instead of the list elements.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} reduce proc identity lst
|
@deffn {Scheme Procedure} reduce proc default lst
|
||||||
@deffnx {Scheme Procedure} reduce-right proc identity lst
|
@deffnx {Scheme Procedure} reduce-right proc default lst
|
||||||
@code{reduce} is a variant of @code{fold} (see above), designed for
|
@code{reduce} is a variant of @code{fold}, where the first call to
|
||||||
cases where the initial value is an ``identity'', so that @var{proc}
|
@var{proc} is on two elements from @var{lst}, rather than one element
|
||||||
can start directly from the first element of @var{lst}.
|
and a given initial value.
|
||||||
|
|
||||||
Consider folding with @code{+} and initial value 0, calls would be for
|
If @var{lst} is empty, @code{reduce} returns @var{default} (this is
|
||||||
instance
|
the only use for @var{default}). If @var{lst} has just one element
|
||||||
|
then that's the return value. Otherwise @var{proc} is called on the
|
||||||
|
elements of @var{lst}.
|
||||||
|
|
||||||
|
Each @var{proc} call is @code{(@var{proc} @var{elem} @var{previous})},
|
||||||
|
where @var{elem} is from @var{lst} (the second and subsequent elements
|
||||||
|
of @var{lst}), and @var{previous} is the return from the previous call
|
||||||
|
to @var{proc}. The first element of @var{lst} is the @var{previous}
|
||||||
|
for the first call to @var{proc}.
|
||||||
|
|
||||||
|
For example, the following adds a list of numbers, the calls made to
|
||||||
|
@code{+} are shown. (Of course @code{+} accepts multiple arguments
|
||||||
|
and can add a list directly, with @code{apply}.)
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(fold + 0 '(4 5 6))
|
(reduce + 0 '(5 6 7)) @result{} 18
|
||||||
@result{}
|
|
||||||
(+ 4 0)
|
(+ 6 5) @result{} 11
|
||||||
(+ 5 4)
|
(+ 7 11) @result{} 18
|
||||||
(+ 6 9)
|
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
The first call @code{(+ 4 0)} is unnecessary, adding 0 to 4 doesn't
|
@code{reduce} can be used instead of @code{fold} where the @var{init}
|
||||||
change that value. The first element @code{4} may as well be the
|
value is an ``identity'', meaning a value which under @var{proc}
|
||||||
initial ``previous'' value argument to @var{proc}. This is what
|
doesn't change the result, in this case 0 is an identity since
|
||||||
@code{reduce} does.
|
@code{(+ 5 0)} is just 5. @code{reduce} avoids that unnecessary call.
|
||||||
|
|
||||||
@example
|
|
||||||
(reduce + 0 '(4 5 6))
|
|
||||||
@result{}
|
|
||||||
(+ 5 4)
|
|
||||||
(+ 6 9)
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The @var{identity} parameter is the return when @var{lst} is empty,
|
|
||||||
that's the only time @var{identity} is used. If @var{lst} has just
|
|
||||||
one element, that's the return with no calls to @var{proc}.
|
|
||||||
|
|
||||||
@code{reduce-right} is a similar variation on @code{fold-right},
|
@code{reduce-right} is a similar variation on @code{fold-right},
|
||||||
working from the end (ie.@: the right) of @var{lst}. Calls in this
|
working from the end (ie.@: the right) of @var{lst}. The last element
|
||||||
case become
|
of @var{lst} is the @var{previous} for the first call to @var{proc},
|
||||||
|
and the @var{elem} values go from the second last.
|
||||||
@example
|
|
||||||
(reduce-right + 0 '(4 5 6))
|
|
||||||
@result{}
|
|
||||||
(+ 5 6)
|
|
||||||
(+ 4 11)
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@code{reduce} should be preferred over @code{reduce-right} if the
|
@code{reduce} should be preferred over @code{reduce-right} if the
|
||||||
order of processing doesn't matter, or can be arranged either way,
|
order of processing doesn't matter, or can be arranged either way,
|
||||||
since @code{reduce} is a little more efficient.
|
since @code{reduce} is a little more efficient.
|
||||||
|
|
||||||
In the above examples of course @code{+} takes any number of
|
|
||||||
arguments, so it can be used on a list just with @code{apply}. An
|
|
||||||
example where that's not the case would be SRFI-19 @code{add-duration}
|
|
||||||
(@pxref{SRFI-19 Time}) on a list of durations,
|
|
||||||
|
|
||||||
@example
|
|
||||||
(use-modules (srfi srfi-19))
|
|
||||||
(reduce add-duration
|
|
||||||
(make-time time-duration 0 0)
|
|
||||||
(list (make-time time-duration 0 4)
|
|
||||||
(make-time time-duration 0 5)
|
|
||||||
(make-time time-duration 0 6)))
|
|
||||||
@result{} #<time duration 15 seconds>
|
|
||||||
@end example
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} unfold p f g seed [tail-gen]
|
@deffn {Scheme Procedure} unfold p f g seed [tail-gen]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue