-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
340 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
TryExperimental.ConcreteResult{T,E} | ||
|
||
Similar to `Union{Ok{T},Err{E}}` but it is a concrete type. | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> using TryExperimental: ConcreteResult | ||
|
||
julia> convert(ConcreteResult{Symbol,Union{BoundsError,DomainError}}, Ok(:a)) | ||
TryExperimental.ConcreteResult (Ok): :a | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,88 @@ | ||
Result{T,E} | ||
TryExperimental.Result{T,E} | ||
|
||
A super type of `Ok{<:T}`, `Err{<:E}`, and `ConcreteResult{T,E}`. | ||
|
||
See also: [`Try.Ok`](@ref), [`Try.Err`](@ref), [`ConcreteResult`](@ref). | ||
|
||
# Extended help | ||
# Examples | ||
|
||
Consider creating an API `tryparse(T, input) -> result`. To simplify the example, let us | ||
define the implementation using `Base.tryparse`: | ||
|
||
```julia | ||
using Try | ||
using TryExperimental | ||
using TryExperimental: Result | ||
|
||
struct InvalidCharError <: Exception end | ||
struct EndOfBufferError <: Exception end | ||
|
||
function __tryparse__(::Type{Int}, str::AbstractString) | ||
isempty(str) && return Err(EndOfBufferError()) | ||
Ok(@something(Base.tryparse(Int, str), return Err(InvalidCharError()))) | ||
end | ||
``` | ||
|
||
where `__tryparse__` is an overload-only API. If it is decided that the call API `tryparse` | ||
should have a limited set of failure modes, it can be enforced by the return value | ||
conversion to a `Result` type. | ||
|
||
```julia | ||
tryparse(T, input)::Result{T,Union{InvalidCharError,EndOfBufferError}} = | ||
__tryparse__(T, input) | ||
``` | ||
|
||
```julia | ||
julia> tryparse(Int, "111") | ||
Try.Ok: 111 | ||
|
||
julia> tryparse(Int, "one") | ||
Try.Err: InvalidCharError() | ||
``` | ||
|
||
## Discussion | ||
|
||
Currently, `Result` is defined as | ||
|
||
```JULIA | ||
Result{T,E} = Union{ConcreteResult{T,E},Ok{<:T},Err{<:E}} | ||
``` | ||
|
||
although there are other possible definitions: | ||
|
||
```JULIA | ||
Result{T,E} = Union{ConcreteResult{<:T,<:E},Ok{<:T},Err{<:E}} | ||
Result{T,E} = Union{ConcreteResult{T,E},Ok{T},Err{E}} | ||
Result{T,E} = AbstractResult{<:T, <:E} | ||
Result = AbstractResult | ||
``` | ||
|
||
The current definition of `Result` may look strange since the type parameters are invariant | ||
for `ConcreteResult` and variant for `Ok` and `Err`. This is chosen given the expectation | ||
that `Union{Ok,Err}` users likely to prefer to let the compiler extra opportunities to | ||
perform pass-dependent optimizations while `ConcreteResult` users likely to prefer control | ||
the exact return type. The definition of `Result` allows these usages simultaneously. | ||
|
||
This let `__tryparse__` implementers opt-in `ConcreteResult` by simply converting their | ||
return value to a `ConcreteResult`: | ||
|
||
```JULIA | ||
function __tryparse__(T::Type, io::MyIO)::ConcreteResult{T,InvalidCharError} | ||
... | ||
end | ||
``` | ||
|
||
This example also demonstrates that `ConcreteResult{T,InvalidCharError}` can automatically | ||
be converted to `Result{T,Union{InvalidCharError,EndOfBufferError}}`. | ||
|
||
As explained above, `Result{T,E}` seems to have nice properties. However, it is not clear | ||
if it works in practice. This is why `Result` is provided from `TryExperimental` but not | ||
from `Try`. For example, `ConcreteResult` may not be useful in practice. If | ||
`ConcreteResult` is dropped, it may be a good idea to define | ||
|
||
``` | ||
Result{T,E} = Union{Ok{T},Err{E}} | ||
``` | ||
|
||
so that the users can explicitly manipulate the variance of each parameters. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
function Base.show(io::IO, ::MIME"text/plain", result::ConcreteResult) | ||
print(io, "TryExperimental.ConcreteResult ") | ||
value = result.value | ||
if value isa Ok | ||
printstyled(io, "(Ok)"; color = :green, bold = true) | ||
print(io, ": ") | ||
show(io, MIME"text/plain"(), Try.unwrap(value)) | ||
else | ||
printstyled(io, "(Err)"; color = :red, bold = true) | ||
print(io, ": ") | ||
ex = Try.unwrap_err(err) | ||
backtrace = err.backtrace | ||
if backtrace === nothing | ||
showerror(io, ex) | ||
else | ||
showerror(io, ex, simplify_backtrace(err.backtrace)) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Try.@function name | ||
|
||
Create a function that can be called without causing a `MethodError`. | ||
|
||
See also: [`istryable`](@ref). | ||
|
||
# Examples | ||
|
||
```julia | ||
julia> using Try | ||
|
||
julia> Try.@function fn; | ||
|
||
julia> fn | ||
fn (tryable function with 1 method) | ||
|
||
julia> fn(1) | ||
Try.Err: Not Implemented: fn(1) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,17 @@ | ||
Err(value::E) -> err::Err{E} | ||
Err{E}(value) -> err::Err{E} | ||
|
||
Indicate that `value` is a "failure" in a sense defined by the API returning this value. | ||
|
||
See: [`iserr`](@ref), [`unwrap_err`](@ref) | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> result = Err(1) | ||
Try.Err: 1 | ||
|
||
julia> Try.unwrap_err(result) | ||
1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,17 @@ | ||
Ok(value::T) -> ok::Ok{T} | ||
Ok{T}(value) -> ok::Ok{T} | ||
|
||
Indicate that `value` is a "success" in a sense defined by the API returning this value. | ||
|
||
See also: [`isok`](@ref), [`unwrap`](@ref) | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> result = Ok(1) | ||
Try.Ok: 1 | ||
|
||
julia> Try.unwrap(result) | ||
1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Try.disable_errortrace() | ||
|
||
Disable stack trace capturing. | ||
|
||
See also: [`Try.enable_errortrace`](@ref). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
Try.enable_errortrace() | ||
|
||
Enable stack trace capturing for each `Err` value creation for debugging. | ||
|
||
See also: [`Try.disable_errortrace`](@ref) | ||
|
||
# Examples | ||
```JULIA | ||
julia> using Try, TryExperimental | ||
|
||
julia> trypush!(Int[], :a) | ||
Try.Err: Not Implemented: tryconvert(Int64, :a) | ||
|
||
julia> Try.enable_errortrace(); | ||
|
||
julia> trypush!(Int[], :a) | ||
Try.Err: Not Implemented: tryconvert(Int64, :a) | ||
Stacktrace: | ||
[1] convert | ||
@ ~/.julia/dev/Try/src/core.jl:28 [inlined] | ||
[2] Break (repeats 2 times) | ||
@ ~/.julia/dev/Try/src/branch.jl:11 [inlined] | ||
[3] branch | ||
@ ~/.julia/dev/Try/src/branch.jl:27 [inlined] | ||
[4] macro expansion | ||
@ ~/.julia/dev/Try/src/branch.jl:49 [inlined] | ||
[5] (::TryExperimental.var"##typeof_trypush!#298")(a::Vector{Int64}, x::Symbol) | ||
@ TryExperimental.Internal ~/.julia/dev/Try/lib/TryExperimental/src/base.jl:69 | ||
[6] top-level scope | ||
@ REPL[4]:1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Try.errtype(::Type{Err{E}}) -> E::Type | ||
Try.errtype(::Err{E}) -> E::Type | ||
|
||
Get the type of the value stored in an `Err`. | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> Try.errtype(Err{Symbol}) | ||
Symbol | ||
|
||
julia> Try.errtype(Err(:a)) | ||
Symbol | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Try.iserr(::Err) -> true | ||
Try.iserr(::Ok) -> false | ||
|
||
Return `true` on an [`Err`](@ref); return `false` on an [`Ok`](@ref). | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> Try.iserr(Try.Err(1)) | ||
true | ||
|
||
julia> Try.iserr(Try.Ok(1)) | ||
false | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Try.isok(::Ok) -> true | ||
Try.isok(::Err) -> false | ||
|
||
Return `true` on an [`Ok`](@ref); return `false` on an [`Err`](@ref). | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> Try.isok(Try.Ok(1)) | ||
true | ||
|
||
julia> Try.isok(Try.Err(1)) | ||
false | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Try.istryable(callable::Any) -> bool::Bool | ||
|
||
Check if a `callable` can be called without causing a `MethodError`. | ||
|
||
See also: [`Try.@function`](@ref). | ||
|
||
# Examples | ||
|
||
```julia | ||
julia> using Try | ||
|
||
julia> Try.@function fn; | ||
|
||
julia> Try.istryable(fn) | ||
true | ||
|
||
julia> Try.istryable(identity) | ||
false | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Try.oktype(::Type{Ok{T}}) -> T::Type | ||
Try.oktype(::Ok{T}) -> T::Type | ||
|
||
Get the type of the value stored in an `Ok`. | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> Try.oktype(Ok{Symbol}) | ||
Symbol | ||
|
||
julia> Try.oktype(Ok(:a)) | ||
Symbol | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Try.unwrap(Ok(value)) -> value | ||
Try.unwrap(::Err) # throws | ||
|
||
Unwrap an [`Ok`](@ref) value; throws on an [`Err`](@ref). | ||
|
||
To obtain a stack trace to the place `Err` is constructed (and not where `unwrap` is | ||
called), use [`Try.enable_errortrace`](@ref). | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> Try.unwrap(Try.Ok(1)) | ||
1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Try.unwrap_err(Err(value)) -> value | ||
Try.unwrap_err(::Ok) # throws | ||
|
||
Unwrap an [`Err`](@ref) value; throws on an [`Ok`](@ref). | ||
|
||
# Examples | ||
```julia | ||
julia> using Try | ||
|
||
julia> Try.unwrap_err(Try.Err(1)) | ||
1 | ||
``` |