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)