Glossary
foldl(step, xf, input, init=...)
# | | | |
# | | | `-- reducible
# | | |
# | | `-- transducer
# | |
# | `-- "bottom" (inner most) reducing function
# |
# `-- transducible process
Reducing step function
Reducing function or Reducing step (function): A reducing function combines result-so-far with the input. It in a narrow sense is a "callable" op
of the signature op(::X, ::Y) :: X
(or op(::X, ::X) :: X
in case for foldxt
) or schematically:
\[(\text{result-so-far}, \text{input}) \mapsto \text{result-so-far}\]
It is the function that can be passed to the classic (non-Transducers.jl) Base.foldl
or Base.reduce
. It is sometimes referred to as a step
or op
. In Transducers.jl, next(rf, ::X, ::Y) :: X
is used instead of a "bare" callable. Furthermore, a reducing function in a loose sense also includes other interfaces such as start(rf, ::X)
and complete(rf, ::X)
.
Transducer
A transducer in Transducers.jl is a transformation xf
that
- transforms an iterator with
xf(itr)
(iterator transformation) - transforms a reducing step function with
xf'(rf)
(reducing function transformation)
Common variable names for transducers are xf
and xform
.
The idea of generalizing the transducer as two kinds of transformation is due to Jan Weidner @jw3126
. See the discussion in JuliaFolds/Transducers.jl#67.
Iterator transformation
As of Transducers.jl 0.4.39, the call overload of Transducer
is interpreted as an iterator transformation. That is to say, the iterator transformation using Base.Iterators
julia> ixf₁ = itr -> Iterators.filter(isodd, itr);
and the iterator transformation in Transducers.jl
julia> ixf₂ = Filter(isodd);
behaves identically:
julia> collect(ixf₁(1:10)) == collect(ixf₂(1:10))
true
Filter(isodd)(1:10)
is an eduction
.
Reducing function transformation
Transducers.jl 0.4.39 also exposes reducing function (RF) transformation with xf'(rf)
(adjoint
):
julia> rf = Filter(isodd)'(+); # equivalent to (acc, x) -> isodd(x) ? acc + x : acc;
julia> rf(0, 2) # `2` filtered out
0
julia> rf(0, 1) # `1` not filtered out
1
Transducer in the narrow sense (Clojure)
The transducer as originally introduced by Rich Hickey is a transformation of reducing step function. Thus, what is referred to as a transducer $\mathrm{xf}$ in Clojure and many other languages is the reducing function transformation xf'
in Transducer.jl.
Since a transducer in the narrow sense maps a reducing function to a reducing function, it can be composed with simple function composition $∘$. When a composite transducer $\mathrm{xf} = \mathrm{xf}_1 \circ \mathrm{xf}_2 \circ ... \circ \mathrm{xf}_n$ to a "bottom" reducing function $\mathrm{rf}_0$, it is processed from right to left just like normal functions:
\[\mathrm{rf} = \mathrm{xf}_1(\mathrm{xf}_2(...(\mathrm{xf}_{n}(\mathrm{rf}_0))))\]
which is equivalent to the following forms in Transducers.jl
rf = xf₁'(xf₂'(...(xfₙ'(rf₀))))
rf = (xf₁' ∘ xf₂' ∘ ... ∘ xfₙ')(rf₀)
rf = (xfₙ ∘ ... ∘ xf₂ ∘ xf₁)'(rf₀)
rf = (xf₁ ⨟ xf₂ ⨟ ... ⨟ xfₙ)(rf₀)
Inner transducer
Given a composition xf₁' ∘ xf₂'
, transducer xf₂
is said to be the inner transducer of xf₁' ∘ xf₂'
. Likewise, xf₂'(rf₀)
is an inner reducing function of xf₁'(xf₂'(rf₀))
.
Reducible collection
Reducible collection (or just Reducible): Any object that can be passed to foldl
and alike is reducible. A reducible collection knows how to apply reducing function to its elements. Iterators are automatically reducible as this is the canonical fallback implementation.
Transducible process
A function that can foldxt reducible collections using transducers is a transducible process. Examples are foldl
and foldxt
. Find more in Transducible processes.
Executor
An executor such as SequentialEx
, ThreadedEx
and DistributedEx
specifies the execution mechanism of a fold. These executors provide a unified mechanism for choosing underlying execution mechanism for Transducers.jl and its related packages such as Folds.jl and FLoops.jl. Typically, the API functions take an executor as the last optional argument. In addition to the executors provided by Transducers.jl (see Executors section in the manual), additional executors are provided from external packages such as FoldsThreads.jl (various thread-based executors) and FoldsCUDA.jl (a CUDA-based executor).
Transducers.jl's executor is a concept similar to KernelAbstractions.jl' device.