Skip to content

Commit

Permalink
Move Base-like APIs to TryExperimental (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
tkf authored Mar 20, 2022
1 parent 1bff512 commit 2e02d81
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 49 deletions.
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ For more explanation, see [Discussion](#discussion) below.
### Basic usage

```julia
julia> using Try
julia> import TryExperimental as Try
```

Try.jl-based API return either an `OK` value
Expand Down Expand Up @@ -63,7 +63,7 @@ Consider an example where an error "bubbles up" from a deep stack of function
calls:

```JULIA
julia> using Try
julia> import TryExperimental as Try

julia> f1(x) = x ? Ok(nothing) : Err(KeyError(:b));

Expand Down Expand Up @@ -128,7 +128,8 @@ example, `Try.eltype` and `Try.length` can be called on arbitrary objects (=
for permission").

```julia
using Try
import TryExperimental as Try
using .Try

function try_map_prealloc(f, xs)
T = Try.@return_err Try.eltype(xs) # macro-based short-circuiting
Expand Down Expand Up @@ -173,16 +174,20 @@ return type of `Union{Ok,Err}`. Thus, the compiler can sometimes prove that
success or failure paths can never be taken:

```julia
julia> using Try, InteractiveUtils
julia> import TryExperimental as Try

julia> using .Try

julia> using InteractiveUtils

julia> @code_typed(Try.first((111, "two", :three)))[2] # always succeeds for non empty tuples
Ok{Int64}
Try.Ok{Int64}

julia> @code_typed(Try.first(()))[2] # always fails for an empty tuple
Err{BoundsError}
Try.Err{BoundsError}

julia> @code_typed(Try.first(Int[]))[2] # both are possible for an array
Union{Ok{Int64}, Err{BoundsError}}
Union{Try.Ok{Int64}, Try.Err{BoundsError}}
```

### Constraining returnable errors
Expand Down Expand Up @@ -213,7 +218,8 @@ Here is an example of providing the call API `tryparse` with the overload API
can return `InvalidCharError()` or `EndOfBufferError()` as an error value:

```julia
using Try
import TryExperimental as Try
using .Try

struct InvalidCharError <: Exception end
struct EndOfBufferError <: Exception end
Expand Down
8 changes: 6 additions & 2 deletions examples/inferrability.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
module UnionTyped
using Try
import TryExperimental
const Try = TryExperimental
using .Try
g(xs) = Ok(xs)
f(xs) = g(xs) |> Try.and_then(xs -> Try.getindex(xs, 1)) |> Try.ok
end # module UnionTyped

module ConcretelyTyped
using Try
import TryExperimental
const Try = TryExperimental
using .Try
g(xs) = Try.ConcreteOk(xs)
function trygetfirst(xs)::Try.ConcreteResult{eltype(xs),BoundsError}
Try.getindex(xs, 1)
Expand Down
21 changes: 21 additions & 0 deletions lib/TryExperimental/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Takafumi Arakaki <[email protected]> and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
10 changes: 10 additions & 0 deletions lib/TryExperimental/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name = "TryExperimental"
uuid = "ae3b139e-64da-4858-8f55-5617df0d650e"
authors = ["Takafumi Arakaki <[email protected]> and contributors"]
version = "0.1.0-DEV"

[deps]
Try = "bf1d0ff0-c4a9-496b-85f0-2b0d71c4f32a"

[compat]
julia = "1.6"
1 change: 1 addition & 0 deletions lib/TryExperimental/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# TryExperimental
52 changes: 52 additions & 0 deletions lib/TryExperimental/src/TryExperimental.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
baremodule TryExperimental

import Try

module InternalPrelude
include("prelude.jl")
end # module InternalPrelude
InternalPrelude.@reexport_try

Try.@function convert
# Try.@function promote

# Collection interface
Try.@function length
Try.@function eltype

Try.@function getindex
Try.@function setindex!

Try.@function first
Try.@function last

Try.@function push!
Try.@function pushfirst!
Try.@function pop!
Try.@function popfirst!

Try.@function put!
Try.@function take!

Try.@function push_nowait!
Try.@function pushfirst_nowait!
Try.@function pop_nowait!
Try.@function popfirst_nowait!

Try.@function put_nowait!
Try.@function take_nowait!

module Internal

import ..TryExperimental
const Try = TryExperimental
using .Try
using .Try: Causes

using Base: IteratorEltype, HasEltype, IteratorSize, HasLength, HasShape

include("base.jl")

end # module Internal

end # baremodule TryExperimental
File renamed without changes.
21 changes: 21 additions & 0 deletions lib/TryExperimental/src/prelude.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Try

macro reexport_try()
exprs = []

mapfoldl(append!, names(Try; all = true); init = exprs) do name
value = try
getproperty(Try, name)
catch err
@error "Cannot access `Try.$name`" exception = (err, catch_backtrace())
return []
end
(value isa Module && value !== Try.Causes) && return []
return [:(const $name = $Try.$name)]
end

public_names = filter(!=(:Try), names(Try))
export_expr = :(export $(public_names...))

return esc(Expr(:block, __source__, exprs..., export_expr))
end
3 changes: 3 additions & 0 deletions lib/TryExperimental/test/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[deps]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TestFunctionRunner = "792026f5-ac9a-4a19-adcb-47b0ce2deb5d"
2 changes: 2 additions & 0 deletions lib/TryExperimental/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
using TestFunctionRunner
TestFunctionRunner.@run
36 changes: 0 additions & 36 deletions src/Try.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,42 +102,6 @@ include("sugar.jl")

end # module Internal

@function convert
# @function promote

# Collection interface
@function length
@function eltype

@function getindex
@function setindex!

@function first
@function last

@function push!
@function pushfirst!
@function pop!
@function popfirst!

@function put!
@function take!

@function push_nowait!
@function pushfirst_nowait!
@function pop_nowait!
@function popfirst_nowait!

@function put_nowait!
@function take_nowait!

module Implementations
using ..Try
using ..Try: Causes
using Base: IteratorEltype, HasEltype, IteratorSize, HasLength, HasShape
include("base.jl")
end # module Implementations

Internal.define_docstrings()

end # baremodule Try
1 change: 1 addition & 0 deletions test/TryTests/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Try = "bf1d0ff0-c4a9-496b-85f0-2b0d71c4f32a"
TryExperimental = "ae3b139e-64da-4858-8f55-5617df0d650e"

[compat]
julia = "1.6"
5 changes: 4 additions & 1 deletion test/TryTests/src/test_base.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
module TestBase

using Test
using Try

import TryExperimental
const Try = TryExperimental
using .Try

function test_convert()
@test Try.unwrap(Try.convert(Int, 1)) === 1
Expand Down
5 changes: 4 additions & 1 deletion test/TryTests/src/test_tools.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
module TestTools

using Test
using Try

import TryExperimental
const Try = TryExperimental
using .Try

function test_curry()
value =
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
using TestFunctionRunner
TestFunctionRunner.@run
TestFunctionRunner.@run(paths = ["../lib/TryExperimental"])

0 comments on commit 2e02d81

Please sign in to comment.