mpfold [-n integer] [-a expr] [-t] [-o expr] expr [expr]
The first expression evaluates to a two-argument procedure, the second
(the initial accumulator) to any value; an unspecified value is the
default if none is specified. -o specifies a single-argument
output procedure; the identity function is the default.
Applies the procedure to each s-expression from the input
in turn, with the current accumulator as the second argument. At the
end, outputs the result of applying the output procedure to the final
accumulator.
If -n is specified, then rather than just the single "current
input s-expression", the first expression's procedure is passed the
specified number of previous s-expressions as well, in extra
arguments. -n defaults to 0. The first call to the procedure
will be performed when sufficient s-expressions have been read (eg,
-n+1 s-expressions) unless -a is specified, when the
procedure will be called for every s-expression, with the result of
the expression passed to -a used as a "default" for slots
that cannot yet be filled.
If -t is specified, then the current, and the specified
number of previous, sexprs are passed as a single list, rather than as
separate arguments to the procedure. The procedure is called for every
input s-expression, with the list being truncated if sufficient
previous values are not available; -a is ignored.
current-input-port is banned, but current-error-port and
current-output-port are accessible.
As with mpmap, the final result of the output procedure may
be any number of values, which will be output sensibly.
Examples
Basic operation
$ echo "1 2 3" | mpfold + 0
6
Using -o
$ echo "1 2 3" | mpfold -o 'number->string' + 0
"6"
$ echo "1 2 3" | mpfold -o '(lambda (x) (* x 2))' + 0
12
Using mplog to demonstrate how the fold-proc is
called
$ echo "1 2 3 4 5 6" | mpfold '(lambda x (mplog "~S" x) 0)' 0
(1 0)
(2 0)
(3 0)
(4 0)
(5 0)
(6 0)
0
The fold-proc is called with two arguments - the current input s-expr
and the accumulator value.
Adding context with -n
$ echo "1 2 3 4 5 6" | mpfold -n 2 '(lambda x (mplog "~S" x) 0)' 0
(3 2 1 0)
(4 3 2 0)
(5 4 3 0)
(6 5 4 0)
0
Note how the fold-proc is not called for 1 or 2; the
first value passed to it is 3 with 2 and 1
as the two requested context items. The fold-proc is now called with
four arguments; the current item, the previous two items, and the
accumulator value.
Using -a as the default context
$ echo "1 2 3 4 5 6" | mpfold -n 2 -a '#f' '(lambda x (mplog "~S" x) 0)' 0
(1 #f #f 0)
(2 1 #f 0)
(3 2 1 0)
(4 3 2 0)
(5 4 3 0)
(6 5 4 0)
0
Note how the fold-proc is now called for all the input sexprs, with
#f filling in for "missing context".
Using -t to pass a list into the fold-proc
$ echo "1 2 3 4 5 6" | mpfold -n 2 -t '(lambda x (mplog "~S" x) 0)' 0
((1) 0)
((2 1) 0)
((3 2 1) 0)
((4 3 2) 0)
((5 4 3) 0)
((6 5 4) 0)
0
The fold-proc now receives two arguments again; the first is a list
containing the current input sexpr and up to 2 (as requested by
-n) previous ones. We are invoked for every input
s-expression, and the list is simply shorter if there have not been
two previous sexprs yet.
Moving average with final mean
$ echo "3 7 2 4 6 4 1" | mpfold -n 2 \
-o '(lambda (x) `(mean ,(/ (cdr x) (car x))))' \
'(lambda (x h1 h2 acc) (write `(moving-mean ,(/ (+ x h1 h2) 3))) (newline) (if acc (cons (+ (car acc) 1) (+ (cdr acc) x)) (cons 3 (+ x h1 h2))))' '#f'
(moving-mean 4)
(moving-mean 4.33333333333333)
(moving-mean 4)
(moving-mean 4.66666666666667)
(moving-mean 3.66666666666667)
(mean 3.85714285714286)
Computing the final mean correctly when using -n without
-a is a little complicated.
Here's a simpler way:
$ echo "3 7 2 4 6 4 1" | mpfold -n 2 -a '#f' \
-o '(lambda (x) `(mean ,(/ (cdr x) (car x))))' \
'(lambda (x h1 h2 acc) (when (and h1 h2) (write `(moving-mean ,(/ (+ x h1 h2) 3))) (newline)) (cons (+ (car acc) 1) (+ (cdr acc) x)))' '(0 . 0)'
(moving-mean 4)
(moving-mean 4.33333333333333)
(moving-mean 4)
(moving-mean 4.66666666666667)
(moving-mean 3.66666666666667)
(mean 3.85714285714286)