From a2022709f01a1ec0fa8bd17456f8c0e4d6339989 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 22 May 2020 15:56:42 -0700 Subject: [PATCH 1/2] Add `INIT` that works with arbitrary operators --- docs/src/index.md | 1 + src/InitialValues.jl | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 26224b54..9c11f1d6 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -6,6 +6,7 @@ ```@docs InitialValues InitialValues.Init +InitialValues.INIT InitialValues.@def InitialValues.@def_monoid InitialValues.@disambiguate diff --git a/src/InitialValues.jl b/src/InitialValues.jl index e1e59443..ff174a65 100644 --- a/src/InitialValues.jl +++ b/src/InitialValues.jl @@ -6,7 +6,7 @@ module InitialValues replace(read(path, String), r"^```julia"m => "```jldoctest README") end InitialValues -export Init, asmonoid +export INIT, Init, asmonoid """ Init(op) :: InitialValue @@ -55,10 +55,44 @@ An abstract super type of all generic initial value types. """ abstract type InitialValue end abstract type SpecificInitialValue{OP} <: InitialValue end -# abstract type GenericIdentity <: AbstractIdentity end +abstract type NonspecificInitialValue <: InitialValue end + +struct TypeOfINIT <: NonspecificInitialValue end + +""" + INIT :: InitialValue + +A generic initial value. Unlike [`Init`](@ref), this does not detect +an error when `INIT` is used with unintended operations. + +# Examples +```jldoctest +julia> using InitialValues + +julia> Init(+) * 0 # `Init(op)` must be used with `op` +ERROR: MethodError: no method matching *(::InitialValues.InitialValueOf{typeof(+)}, ::Int64) +[...] + +julia> INIT * 123 +123 + +julia> foldl(+, 1:3, init=INIT) +6 +""" +const INIT = TypeOfINIT() + +function Base.show(io::IO, ::TypeOfINIT) where {OP} + if !get(io, :limit, false) + # Don't show full name in REPL etc.: + print(io, "InitialValues.") + end + print(io, "INIT") +end struct InitialValueOf{OP} <: SpecificInitialValue{OP} end +const GenericInitialValue{OP} = Union{SpecificInitialValue{OP},NonspecificInitialValue} + function Base.show(io::IO, ::InitialValueOf{OP}) where {OP} if !get(io, :limit, false) # Don't show full name in REPL etc.: @@ -72,7 +106,7 @@ function Base.show(io::IO, ::InitialValueOf{OP}) where {OP} end end -itypeof_impl(op) = :(SpecificInitialValue{typeof($op)}) +itypeof_impl(op) = :(GenericInitialValue{typeof($op)}) @eval itypeof(op) = $(itypeof_impl(:op)) """ From 82529194370cdc8744256df596a19fe3cafd1780 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 23 May 2020 14:15:47 -0700 Subject: [PATCH 2/2] Test INIT --- test/test_basics.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_basics.jl b/test/test_basics.jl index 87697675..9e2cb609 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -8,6 +8,9 @@ OPS = [*, +, |, &, min, max, Base.add_sum, Base.mul_prod] @testset for op in OPS @test op(Init(op), :anything) === :anything + @test op(:anything, Init(op)) === :anything + @test op(INIT, :anything) === :anything + @test op(:anything, INIT) === :anything @test hasinitialvalue(op) @test hasinitialvalue(typeof(op)) @test isknown(Init(op)) @@ -26,6 +29,11 @@ end @test repr(Init(op)) == "InitialValues.$desired" @test string(Init(op)) == "InitialValues.$desired" end + @testset "INIT" begin + @test repr(INIT; context=:limit => true) == "INIT" + @test repr(INIT) == "InitialValues.INIT" + @test string(INIT) == "InitialValues.INIT" + end end @testset "hasinitialvalue" begin