From 1049d50e6e8f680e4961fcb14d21004d127f691e Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 24 Apr 2022 02:54:28 -0400 Subject: [PATCH] Add `Try.transpose` --- docs/src/index.md | 1 + src/Try.jl | 1 + src/docs/transpose.md | 17 +++++++++++++++++ src/tools.jl | 21 +++++++++++++++++++++ test/TryTests/src/test_tools.jl | 15 +++++++++++++++ 5 files changed, 55 insertions(+) create mode 100644 src/docs/transpose.md diff --git a/docs/src/index.md b/docs/src/index.md index 6152542..610549f 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -16,6 +16,7 @@ Try.unwrap_err Try.oktype Try.errtype Try.map +Try.transpose ``` ## Short-circuit evaluation diff --git a/src/Try.jl b/src/Try.jl index 875db05..54e6804 100644 --- a/src/Try.jl +++ b/src/Try.jl @@ -35,6 +35,7 @@ struct IsOkError <: InternalPrelude.Exception end function map end +function transpose end macro and_return end function var"@?" end diff --git a/src/docs/transpose.md b/src/docs/transpose.md new file mode 100644 index 0000000..326b4b1 --- /dev/null +++ b/src/docs/transpose.md @@ -0,0 +1,17 @@ + Try.transpose(result_of_maybe) -> maybe_of_result + Try.transpose(maybe_of_result) -> result_of_maybe + +Transpose `Union{Ok,Err}` wrapped in `Union{Some,Nothing}` and vice versa. + +# Extended help +## Examples +```julia +using Try + +@assert Try.transpose(Ok(nothing)) === nothing +@assert Try.transpose(Ok(Some(1))) === Some(Ok(1)) +@assert Try.transpose(Err(:error)) === Some(Err(:error)) +@assert Try.transpose(Some(Ok(1))) === Try.Ok(Some(1)) +@assert Try.transpose(Some(Err(:error))) === Try.Err(:error) +@assert Try.transpose(nothing) === Try.Ok() +``` diff --git a/src/tools.jl b/src/tools.jl index b5a86ca..66794f2 100644 --- a/src/tools.jl +++ b/src/tools.jl @@ -21,3 +21,24 @@ TryMap(::Type{T}) where {T} = TryMap{Type{T}}(T) (f::TryMap)(x) = Try.map(f.f, x) Try.map(f::F) where {F} = TryMap(f) + +function Try.transpose(ok::Ok) + maybe = Try.unwrap(ok)::Union{Some,Nothing} + if maybe === nothing + nothing + else + Some(Ok(something(maybe))) + end +end +Try.transpose(err::Err) = Some(err) + +Try.transpose(::Nothing) = Ok() +function Try.transpose(some::Some) + result = something(some) + if Try.isok(result) + Ok(Some(Try.unwrap(result))) + else + # Need to "forget" about any Ok value type information: + Err(Try.unwrap_err(result)) + end +end diff --git a/test/TryTests/src/test_tools.jl b/test/TryTests/src/test_tools.jl index dcf1989..9b8b2bd 100644 --- a/test/TryTests/src/test_tools.jl +++ b/test/TryTests/src/test_tools.jl @@ -151,4 +151,19 @@ function test_map() @test Try.map(x -> x + 1, nothing) === nothing end +function test_double_transpose() + @testset for x in [ + # Result-of-Maybe + Ok(Some(1)), + Ok(nothing), + Err(:error), + # Maybe-of-Result + Some(Ok(1)), + Some(Err(:error)), + nothing, + ] + @test Try.transpose(Try.transpose(x)) == x + end +end + end # module