Home

InitialValues.jl

InitialValuesModule.

InitialValues.jl: Canonical default initial values ("left identity") for Julia

Stable Dev Build Status Codecov Coveralls Aqua QA

InitialValues.jl provides a generic singleton initial value Init(f) that can be used as a₀ in f(a₀, x). For a binary operator op, it means that Init(op) acts like the left identity for any type of x:

julia> using InitialValues

julia> Init(+) + 1
1

julia> Init(+) + 1.0
1.0

julia> foldl(+, 1:3, init=Init(+))
6

Following methods are defined for the binary operators in Base:

julia> Init(*) * 1
1

julia> Init(&) & 1
1

julia> Init(|) | 1
1

julia> min(Init(min), 1)
1

julia> max(Init(max), 1)
1

julia> Base.add_sum(Init(Base.add_sum), 1)
1

julia> Base.mul_prod(Init(Base.mul_prod), 1)
1

Init 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!!(Init(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=Init(push!!))
3-element Array{Union{Missing, Float64},1}:
 1.0
  missing
 2.0

Transducers.jl extensively uses Init.

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.

source
InitialValues.InitFunction.
Init(op) :: InitialValue

Create a generic (left) identity for a binary operator op. For general binary function, it provides an identity-like generic default value (see BangBang.push!!).

Examples

julia> using InitialValues

julia> Init(*) isa InitialValues.InitialValue
true

julia> Init(*) * 1
1

julia> Init(*) * missing
missing

julia> Init(*) * "right"
"right"

julia> Init(*) * :actual_anything_works
:actual_anything_works

julia> foldl(+, 1:3, init=Init(+))
6

julia> float(Init(*))
1.0

julia> Integer(Init(+))
0
source
InitialValues.@def op [y = :x]

Define a generic (left) identity for a binary operator op. Specify the second argument for a binary function in general.

InitialValues.@def op is expanded to

op(::SpecificInitialValue{typeof(op)}, x) = x
InitialValues.hasinitialvalue(::Type{typeof(op)}) = true

For operations like push!, it is useful to define the returned value to be different from x. This can be done by using the second argument to the maco; i.e., InitialValues.@def push! [x] is expanded to

push!(::SpecificInitialValue{typeof(push!)}, x) = [x]
InitialValues.hasinitialvalue(::Type{typeof(push!)}) = true

Note that the second argument to op is always x.

source
InitialValues.@disambiguate op RightType [y = :x]

Disambiguate the method introduced by @def.

It is expanded to

op(::SpecificInitialValue{typeof(op)}, x::RightType) = x
source
InitialValues.hasinitialvalue(op) :: Bool

Examples

julia> using InitialValues

julia> all(InitialValues.hasinitialvalue, [
           *,
           +,
           &,
           |,
           min,
           max,
           Base.add_sum,
           Base.mul_prod,
       ])
true

julia> InitialValues.hasinitialvalue((x, y) -> x + y)
false
source
InitialValues.isknownFunction.
InitialValues.isknown(::InitialValue) :: Bool

Examples

julia> using InitialValues

julia> InitialValues.isknown(Init(+))
true

julia> InitialValues.isknown(Init((x, y) -> x + y))
false
source
InitialValues.InitialValue

An abstract super type of all generic initial value types.

source