Skip to content

Canonical default initial values and identity elements for Julia

License

Notifications You must be signed in to change notification settings

JuliaFolds/InitialValues.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

InitialValues.jl: Canonical default initial values and identity elements for Julia

Stable Dev GitHub Actions Codecov Coveralls Aqua QA

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.