Skip to content

Instantly share code, notes, and snippets.

@KristofferC
Last active November 3, 2018 04:35
Show Gist options
  • Save KristofferC/a0c6eccb1ac764842ae3b6db0779bba9 to your computer and use it in GitHub Desktop.
Save KristofferC/a0c6eccb1ac764842ae3b6db0779bba9 to your computer and use it in GitHub Desktop.
import Base: convert, isassigned, getindex
struct expected{T,E}
v::Union{T,E}
ok::Bool
end
convert(::Type{expected{T,E}}, v::T) where {T, E} = expected{T, E}(v, true)
convert(::Type{expected{T,E}}, v::E) where {T, E} = expected{T, E}(v, false)
convert(::Type{expected{T,T}}, v::T) where {T} = expected{T, T}(v, true)
struct unexpected{T}
v::T
end
# `unexpected` needed to disambiguate when `T == E` and want return an unexpected
convert(::Type{expected{T,E}}, v::unexpected{E}) where {T, E} = expected{T, E}(v.v, false)
isassigned(e::expected) = e.ok
(getindex(e::expected{T})::T) where {T} = isassigned(e) ? e.v : throw(e.v)
# Example usage
function relative(a::Float64, b::Float64)::expected{Float64, ErrorException}
if a == 0
return ErrorException("cannot compute relative to 0")
else
return (b-a) / a
end
end
@show x = relative(3.0, 2.0)
@show isassigned(x)
@show x[]
@show y = relative(0.0, 2.0)
@show isassigned(y)
# y[] boom
# Same type of expected and unexpected requires `unexpected`
function good_int_or_bad_int(a)::expected{Int, Int}
if a < 3
return a
else
return unexpected(a)
end
end
@show z = good_int_or_bad_int(1)
@show isassigned(z)
@show q = good_int_or_bad_int(4)
@show isassigned(q)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment