From ab235a19c6a69e4d3e95e834e2cbd5e331631ee2 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Mon, 21 Mar 2022 00:45:02 -0700 Subject: [PATCH] Move `Result` to `TryExperimental` (#29) --- README.md | 3 ++ docs/src/experimental.md | 4 ++ docs/src/index.md | 1 - lib/TryExperimental/src/TryExperimental.jl | 7 +++- lib/TryExperimental/src/concrete.jl | 42 +++++++++++++++++++ .../TryExperimental/src}/docs/Result.md | 0 src/Try.jl | 5 +-- src/concrete.jl | 11 ----- src/core.jl | 30 ------------- src/docs/Err.md | 3 +- src/docs/Ok.md | 3 +- 11 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 lib/TryExperimental/src/concrete.jl rename {src => lib/TryExperimental/src}/docs/Result.md (100%) delete mode 100644 src/concrete.jl diff --git a/README.md b/README.md index e3463da..9c40fcd 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,9 @@ can return `InvalidCharError()` or `EndOfBufferError()` as an error value: ```julia using Try, TryExperimental +const Result{T,E} = Union{Ok{<:T},Err{<:E}} +# using TryExperimental: Result # (almost equivalent) + struct InvalidCharError <: Exception end struct EndOfBufferError <: Exception end diff --git a/docs/src/experimental.md b/docs/src/experimental.md index ec49493..3151f2d 100644 --- a/docs/src/experimental.md +++ b/docs/src/experimental.md @@ -1,5 +1,9 @@ # Experimental +```@docs +TryExperimental.Result +``` + ## [Customizing short-circuit evaluation](@id customize-short-circuit) ```@docs diff --git a/docs/src/index.md b/docs/src/index.md index 7f2269c..283dd1e 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -2,7 +2,6 @@ ```@docs Try -Result Ok Err ``` diff --git a/lib/TryExperimental/src/TryExperimental.jl b/lib/TryExperimental/src/TryExperimental.jl index 93b4cdc..3fff29b 100644 --- a/lib/TryExperimental/src/TryExperimental.jl +++ b/lib/TryExperimental/src/TryExperimental.jl @@ -38,8 +38,6 @@ abstract type EmptyError <: Exception end abstract type ClosedError <: Exception end # abstract type FullError <: Exception end -const ConcreteResult = Try.Internal.ConcreteResult - macro and_then end macro or_else end @@ -54,6 +52,7 @@ module Internal import ..TryExperimental: @and_then, @or_else using ..TryExperimental: TryExperimental, Causes using Try +using Try.Internal: AbstractResult for n in names(TryExperimental; all = true) startswith(string(n), "try") || continue @@ -64,12 +63,16 @@ end using Base.Meta: isexpr using Base: IteratorEltype, HasEltype, IteratorSize, HasLength, HasShape +include("concrete.jl") include("sugars.jl") include("causes.jl") include("base.jl") end # module Internal +const Result = Internal.Result +const ConcreteResult = Internal.ConcreteResult + # TODO: move this to Maybe.jl baremodule Maybe function ok end diff --git a/lib/TryExperimental/src/concrete.jl b/lib/TryExperimental/src/concrete.jl new file mode 100644 index 0000000..bcea1e9 --- /dev/null +++ b/lib/TryExperimental/src/concrete.jl @@ -0,0 +1,42 @@ +const DynamicResult{T,E} = Union{Ok{T},Err{E}} + +function _ConcreteResult end + +struct ConcreteResult{T,E} <: AbstractResult{T,E} + value::DynamicResult{T,E} + + global _ConcreteResult(::Type{T}, ::Type{E}, value) where {T,E} = new{T,E}(value) +end + +# Is this mixture of invariance and covariance good? +const Result{T,E} = Union{ConcreteResult{T,E},DynamicResult{<:T,<:E}} + +Try.unwrap(result::ConcreteResult) = Try.unwrap(result.value) +Try.unwrap_err(result::ConcreteResult) = Try.unwrap_err(result.value) +Try.isok(result::ConcreteResult) = result.value isa Ok +Try.iserr(result::ConcreteResult) = result.value isa Err + +_concrete(result::Ok) = _ConcreteResult(Try.oktype(result), Union{}, result) +_concrete(result::Err) = _ConcreteResult(Union{}, Try.errtype(result), result) + +Base.convert(::Type{ConcreteResult{T,E}}, result::Ok) where {T,E} = + _ConcreteResult(T, E, convert(Ok{T}, result)) +Base.convert(::Type{ConcreteResult{T}}, result::Ok) where {T} = + _ConcreteResult(T, Union{}, convert(Ok{T}, result)) + +Base.convert(::Type{ConcreteResult{T,E}}, result::Err) where {T,E} = + _ConcreteResult(T, E, convert(Err{E}, result)) +Base.convert(::Type{ConcreteResult{<:Any,E}}, result::Err) where {E} = + _ConcreteResult(Union{}, E, convert(Err{E}, result)) + +function Base.convert( + ::Type{ConcreteResult{T,E}}, + result::ConcreteResult{T′,E′}, +) where {T,E,T′<:T,E′<:E} + value = result.value + if value isa Ok + return _ConcreteResult(T, E, Ok{T}(value.value)) + else + return _ConcreteResult(T, E, Err{E}(value.value)) + end +end diff --git a/src/docs/Result.md b/lib/TryExperimental/src/docs/Result.md similarity index 100% rename from src/docs/Result.md rename to lib/TryExperimental/src/docs/Result.md diff --git a/src/Try.jl b/src/Try.jl index 0d81c9f..e4cabfc 100644 --- a/src/Try.jl +++ b/src/Try.jl @@ -1,6 +1,6 @@ baremodule Try -export @?, Ok, Err, Result +export @?, Ok, Err module InternalPrelude abstract type AbstractResult{T,E} end @@ -54,7 +54,6 @@ using ..Try.InternalPrelude: AbstractResult, _IsOkError include("ExternalDocstrings.jl") using .ExternalDocstrings: @define_docstrings -include("concrete.jl") include("core.jl") include("show.jl") include("errortrace.jl") @@ -64,8 +63,6 @@ include("branch.jl") end # module Internal -const Result = Internal.Result - Internal.@define_docstrings end # baremodule Try diff --git a/src/concrete.jl b/src/concrete.jl deleted file mode 100644 index 51cf0f3..0000000 --- a/src/concrete.jl +++ /dev/null @@ -1,11 +0,0 @@ -const DynamicResult{T,E} = Union{Ok{T},Err{E}} - -function _ConcreteResult end - -struct ConcreteResult{T,E} <: AbstractResult{T,E} - value::DynamicResult{T,E} - - global _ConcreteResult(::Type{T}, ::Type{E}, value) where {T,E} = new{T,E}(value) -end - -const Result{T,E} = Union{ConcreteResult{<:T,<:E},DynamicResult{<:T,<:E}} diff --git a/src/core.jl b/src/core.jl index 287dd2d..1a686a4 100644 --- a/src/core.jl +++ b/src/core.jl @@ -3,15 +3,12 @@ Try.Ok(::Type{T}) where {T} = Try.Ok{Type{T}}(T) Try.Err(value) = Try.Err(value, maybe_backtrace()) Try.Err{E}(value) where {E<:Exception} = Try.Err{E}(value, maybe_backtrace()) -Try.unwrap(result::ConcreteResult) = Try.unwrap(result.value) Try.unwrap(ok::Ok) = ok.value Try.unwrap(err::Err) = _throw(err) -Try.unwrap_err(result::ConcreteResult) = Try.unwrap_err(result.value) Try.unwrap_err(ok::Ok) = throw(Try.IsOkError(ok)) Try.unwrap_err(err::Err) = err.value -_throw(err::ConcreteResult) = _throw(err.value) function _throw(err::Err) if err.backtrace === nothing throw(err.value) @@ -34,31 +31,6 @@ Base.convert(::Type{Err{E}}, err::Err) where {E} = Err{E}(err.value) # chain-of-custody Julep. Maybe this should be done only when the destination # type is `AbstractResult{<:Any,E′}` s.t. `!(err.value isa E′)`. -_concrete(result::Ok) = _ConcreteResult(Try.oktype(result), Union{}, result) -_concrete(result::Err) = _ConcreteResult(Union{}, Try.errtype(result), result) - -Base.convert(::Type{ConcreteResult{T,E}}, result::Ok) where {T,E} = - _ConcreteResult(T, E, convert(Ok{T}, result)) -Base.convert(::Type{ConcreteResult{T}}, result::Ok) where {T} = - _ConcreteResult(T, Union{}, convert(Ok{T}, result)) - -Base.convert(::Type{ConcreteResult{T,E}}, result::Err) where {T,E} = - _ConcreteResult(T, E, convert(Err{E}, result)) -Base.convert(::Type{ConcreteResult{<:Any,E}}, result::Err) where {E} = - _ConcreteResult(Union{}, E, convert(Err{E}, result)) - -function Base.convert( - ::Type{ConcreteResult{T,E}}, - result::ConcreteResult{T′,E′}, -) where {T,E,T′<:T,E′<:E} - value = result.value - if value isa Ok - return _ConcreteResult(T, E, Ok{T}(value.value)) - else - return _ConcreteResult(T, E, Err{E}(value.value)) - end -end - Try.oktype(::Type{R}) where {T,R<:AbstractResult{T}} = T Try.oktype(result::AbstractResult) = Try.oktype(typeof(result)) @@ -67,8 +39,6 @@ Try.errtype(result::AbstractResult) = Try.errtype(typeof(result)) Try.isok(::Ok) = true Try.isok(::Err) = false -Try.isok(result::ConcreteResult) = result.value isa Ok Try.iserr(::Ok) = false Try.iserr(::Err) = true -Try.iserr(result::ConcreteResult) = result.value isa Err diff --git a/src/docs/Err.md b/src/docs/Err.md index eccbd46..e7e83ca 100644 --- a/src/docs/Err.md +++ b/src/docs/Err.md @@ -1 +1,2 @@ - Err{E} <: Result{T,E} + Err(value::E) -> err::Err{E} + Err{E}(value) -> err::Err{E} diff --git a/src/docs/Ok.md b/src/docs/Ok.md index d2a10bb..8fd8cd6 100644 --- a/src/docs/Ok.md +++ b/src/docs/Ok.md @@ -1 +1,2 @@ - Ok{T} <: Result{T,E} + Ok(value::T) -> ok::Ok{T} + Ok{T}(value) -> ok::Ok{T}