diff --git a/src/Try.jl b/src/Try.jl index 3b89ba6..8201052 100644 --- a/src/Try.jl +++ b/src/Try.jl @@ -36,6 +36,7 @@ end macro and_return end function var"@?" end +function var"@return" end function and_then end function or_else end diff --git a/src/branch.jl b/src/branch.jl index 44db4f7..3232ab5 100644 --- a/src/branch.jl +++ b/src/branch.jl @@ -66,6 +66,18 @@ macro and_return(ex) end end +const var"@_return" = Try.var"@return" +macro _return(ex) + quote + br = branch($(esc(ex))) + if br isa Continue + return valueof(br) + else + valueof(br) + end + end +end + function Try.and_then(f, result) br = branch(result) if br isa Continue diff --git a/src/docs/@return.md b/src/docs/@return.md new file mode 100644 index 0000000..3a6724f --- /dev/null +++ b/src/docs/@return.md @@ -0,0 +1,49 @@ + Try.@and_return result -> result′ + +Evaluate `f(value)` if `result` is a "success" wrapping a `value`; otherwise, a "failure" +`value` as-is. + +| Invocation | Equivalent code | +|:--- |:--- | +| `@and_return Ok(value)` | `value` | +| `@and_return err::Err` | `return err` | +| `@and_return Some(value)` | `value` | +| `@and_return nothing` | `return nothing` | + +See also: [`@?`](@ref) [`and_then`](@ref), [`or_else`](@ref). + +# Extended help + +## Examples + +Let's define a function `nitems` that works like `length` but falls back to iteration-based +counting: + +```julia +using Try, TryExperimental + +function trygetnitems(xs) + Try.@and_return trygetlength(xs) + Ok(count(Returns(true), xs)) +end + +nitems(xs) = Try.unwrap(trygetnitems(xs)) + +nitems(1:3) + +# output +3 +``` + +`nitems` works with arbitrary iterator, including the ones that does not have `length`: + +```julia +ch = foldl(push!, 1:3; init = Channel{Int}(3)) +close(ch) + +nitems(ch) + +# output +3 +``` + diff --git a/test/TryTests/src/test_tools.jl b/test/TryTests/src/test_tools.jl index 532b498..bbaa0f2 100644 --- a/test/TryTests/src/test_tools.jl +++ b/test/TryTests/src/test_tools.jl @@ -22,6 +22,11 @@ function nitems(xs) end |> Try.unwrap end +function nitems2(xs) + Try.@return trygetlength(xs) + count(Returns(true), xs) +end + function test_and_return() @test Try.unwrap(trygetnitems(1:3)) == 3 @@ -30,7 +35,7 @@ function test_and_return() @test Try.unwrap(trygetnitems(ch)) == 3 end -function test_or_else() +function check_nitems(nitems) @test nitems(1:3) == 3 ch = foldl(push!, 1:3; init = Channel{Int}(3)) @@ -38,6 +43,9 @@ function test_or_else() @test nitems(ch) == 3 end +test_or_else() = check_nitems(nitems) +test_return() = check_nitems(nitems2) + try_map_prealloc(f, xs) = Try.and_then(trygetlength(xs)) do n Try.and_then(trygeteltype(xs)) do T