InitialValues.jl
InitialValues.jl copied to clipboard
Canonical default initial values and identity elements for Julia
InitialValues.jl: Canonical default initial values and identity elements for Julia
InitialValues.jl provides a generic singleton initial value InitialValue(f)
that can be used as a₀ in f(a₀, x). For a binary operator op,
it means that InitialValue(op) acts like the identity for any type of x:
julia> using InitialValues
julia> InitialValue(+) + 1
1
julia> 1.0 + InitialValue(+)
1.0
julia> foldl(+, 1:3, init=InitialValue(+))
6
Following methods are defined for the binary operators in Base:
julia> InitialValue(*) * 1
1
julia> InitialValue(&) & 1
1
julia> InitialValue(|) | 1
1
julia> min(InitialValue(min), 1)
1
julia> max(InitialValue(max), 1)
1
julia> Base.add_sum(InitialValue(Base.add_sum), 1)
1
julia> Base.mul_prod(InitialValue(Base.mul_prod), 1)
1
InitialValue is not called Identity because it is useful to define it for
functions that are not binary operator (symmetric in signature). For
example, push!! in BangBang.jl
defines
julia> using BangBang
julia> push!!(InitialValue(push!!), 1)
1-element Array{Int64,1}:
1
This provides a powerful pattern when combined with foldl:
julia> foldl(push!!, (1, missing, 2.0), init=InitialValue(push!!))
3-element Array{Union{Missing, Float64},1}:
1.0
missing
2.0
Transducers.jl extensively
uses InitialValue.
As binary operators like * in Base are heavily overloaded,
creating generic definitions such as above could have introduced
method ambiguities. To protect against such situation, InitialValues.jl is
tested using Aqua.jl.