FunctionChains.jl
FunctionChains.jl provides chained/composed functions with functionality beyond Base.ComposedFunction
, as well as some other ways of combining functions.
The package defines the function fchain
that turns a sequence of functions into a callable function chain. Functions are applied in the order they are given, so fchain(f, g, h)
and fchain((f, g, h))
are semantically equivalent to h ∘ g ∘ f
.
Function chains can be based on tuples of functions but also on arrays (e.g. fchain([x -> i * x for i in 1:4])
) or generators/iterators (e.g. fchain((x -> i * x for i in 1:4))
) of functions. fchain
will always try to generate type-stable function chains if possible.
The function chain generated by fchain
supports InverseFunctions.inverse
and/or ChangesOfVariables.with_logabsdet_jacobian
, as well as the Adapt
, Functors
and FlexiMaps
APIs, if all functions in the chain do support the respective API.
frepeat(f, n)
and f∘̂ n
build a chain of n
repetitions of function f
. Use fcomp(f, g, h)
to compose functions in the order f ∘ g ∘ h
, equivalent to fchain(h, g, f)
.
fcprod(fs)
constructs a Cartesian product of functions.
ffanout(fs)
constructs a function fanout.
FunctionChains also exports the convenience functions asfunction(f)
and typed_callable(f)
that wrap a callable f
in a properly typed callable function (object) if necessary, e.g. if f
is a type (constructor).
Function chains
Example:
using FunctionChains
f = fchain(Complex, sqrt)
f(-1)
# output
0.0 + 1.0im
g = fchain((x -> i * x for i in 1:4))
g(1.75)
# output
42.0
The functions chains f
and g
in this example are both type stable
using Test
@inferred f(-1)
@inferred g(1.75)
In general, type stability will depend on the functions in the sequence and the type of the sequence itself.
Function products
A Cartesian product of functions applies some kind of collection (a tuple, array, NamedTuple
or an iterable in general) of functions to a collection (with the same shape) of values, in an component/element-wise fashion:
fp = fcprod(x -> 2*x, x -> 3*x)
fp((4, 5))
# output
(8, 15)
fp = fcprod((a = x -> 2*x, b = x -> 3*x))
fp((a = 4, b = 5))
# output
(a = 8, b = 15)
Function fanouts
A function fanout applies some kind of collection a functions to single input, separately, resulting in a collection of the outputs:
fp = ffanout([Base.Fix1(*, 2), Base.Fix1(*, 3), Base.Fix1(*, 4)])
fp(4) == [8, 12, 16]
# output
true
fp = ffanout((a = x -> 2*x, b = x -> 3*x))
fp(4)
# output
(a = 8, b = 12)