I've recently added another library to Rebellion, this one for
reducers. A
reducer is a way to combine a series of values:
> (require rebellion/streaming/reducer)
> (reduce into-sum 1 2 3 4 5)
15
You can reduce any sequence using `reduce-all`:
> (reduce-all into-product (in-range 1 20))
121645100408832000
You can make a reducer from any fold:
> (define into-reversed-list (make-fold-reducer (lambda (lst v) (cons v lst)) '()))
> (reduce-all into-reversed-list (in-range 1 10)
'(9 8 7 6 5 4 3 2 1)
You can use `for/reducer` and `for*/reducer` to fold over any `for`-loop using a reducer:
> (for/reducer into-reversed-list
([n (in-range 2 20)]
#:when (prime? n))
n)
'(19 17 13 11 7 5 3 2)
And you can implement your own `for/...` macros using a reducer:
> (define-syntaxes (for/reversed-list for*/reversed-list)
(make-reducer-based-for-comprehensions #'into-reversed-list))
> (for/reversed-list ([n (in-range 2 20)]
#:when (prime? n))
n)
'(19 17 13 11 7 5 3 2)
Folds are only the most basic type of reducer: not all reducers are as simple as a plain fold. Reducers can use hidden mutable state to make reduction performant, and reducers can short-circuit and return a result without iterating through the entire sequence. See the
rebellion/streaming/reducer documentation for more details, as well as instructions on how to make your own reducers. To use, install Rebellion with `raco pkg install rebellion` and import the reducers library with `(require rebellion/streaming/reducer)`.
This library is currently in an
experimental alpha state. I might break your code. Warn me before seriously depending on this,
especially if you won't be using it in an open-source package in the package catalog (where the package build server can alert me if I break you).