From abbf34e53f88fc38233e4377611b71646f5ca3c9 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 24 Apr 2022 01:02:27 -0700 Subject: [PATCH] Add `Try.map` (#48) --- docs/src/index.md | 1 + src/Try.jl | 3 +++ src/docs/map.md | 25 +++++++++++++++++++++++++ src/tools.jl | 23 +++++++++++++++++++++++ test/TryTests/src/test_tools.jl | 7 +++++++ 5 files changed, 59 insertions(+) create mode 100644 src/docs/map.md create mode 100644 src/tools.jl diff --git a/docs/src/index.md b/docs/src/index.md index 1722019..6152542 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -15,6 +15,7 @@ Try.unwrap Try.unwrap_err Try.oktype Try.errtype +Try.map ``` ## Short-circuit evaluation diff --git a/src/Try.jl b/src/Try.jl index b80f480..875db05 100644 --- a/src/Try.jl +++ b/src/Try.jl @@ -34,6 +34,8 @@ struct IsOkError <: InternalPrelude.Exception InternalPrelude._IsOkError(ok) = new(ok) end +function map end + macro and_return end function var"@?" end function var"@return" end @@ -57,6 +59,7 @@ using .ExternalDocstrings: @define_docstrings include("core.jl") include("errortrace.jl") +include("tools.jl") include("branch.jl") include("show.jl") diff --git a/src/docs/map.md b/src/docs/map.md new file mode 100644 index 0000000..3efdc74 --- /dev/null +++ b/src/docs/map.md @@ -0,0 +1,25 @@ + Try.map(f, result) -> result′ + Try.map(f, Ok(value)) -> Ok(f(value)) + Try.map(_, err::Err) -> err + Try.map(f, Some(value)) -> Some(f(value)) + Try.map(_, nothing) -> nothing + Try.map(f) -> result -> Try.map(f, result) + +Apply `f` in the value wrapped in the "successful" result. + +# Examples + +```julia +julia> using Try + +julia> Try.map(x -> x + 1, Ok(1)) +Try.Ok: 2 + +julia> Try.map(x -> x + 1, Err(KeyError(:a))) +Try.Err: KeyError: key :a not found + +julia> Try.map(x -> x + 1, Some(1)) +Some(2) + +julia> Try.map(x -> x + 1, nothing) +``` diff --git a/src/tools.jl b/src/tools.jl new file mode 100644 index 0000000..b5a86ca --- /dev/null +++ b/src/tools.jl @@ -0,0 +1,23 @@ +Try.map(f, ok::Ok) = Ok(f(ok.value)) +Try.map(_, err::Err) = err + +function Try.map(f, result) + if Try.isok(result) + Ok(f(Try.unwrap(result))) + else + # Need to "forget" about any Ok value type information: + Err(Try.unwrap_err(result)) + end +end + +Try.map(f, some::Some) = Some(f(something(some))) +Try.map(_, ::Nothing) = nothing + +struct TryMap{F} <: Function + f::F +end +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) diff --git a/test/TryTests/src/test_tools.jl b/test/TryTests/src/test_tools.jl index a0573c1..dcf1989 100644 --- a/test/TryTests/src/test_tools.jl +++ b/test/TryTests/src/test_tools.jl @@ -144,4 +144,11 @@ function test_macro() @test demo_macro(1:0) === :oob end +function test_map() + @test Try.map(x -> x + 1, Ok(1)) == Try.Ok(2) + @test Try.map(x -> x + 1, Err(KeyError(:a))) == Err(KeyError(:a)) + @test Try.map(x -> x + 1, Some(1)) == Some(2) + @test Try.map(x -> x + 1, nothing) === nothing +end + end # module