From 2e02d81bafdca9cef53e010ea6f4fab05af8c13f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 19 Mar 2022 21:07:52 -0700 Subject: [PATCH] Move Base-like APIs to TryExperimental (#13) --- README.md | 22 +++++---- examples/inferrability.jl | 8 +++- lib/TryExperimental/LICENSE | 21 +++++++++ lib/TryExperimental/Project.toml | 10 +++++ lib/TryExperimental/README.md | 1 + lib/TryExperimental/src/TryExperimental.jl | 52 ++++++++++++++++++++++ {src => lib/TryExperimental/src}/base.jl | 0 lib/TryExperimental/src/prelude.jl | 21 +++++++++ lib/TryExperimental/test/Project.toml | 3 ++ lib/TryExperimental/test/runtests.jl | 2 + src/Try.jl | 36 --------------- test/TryTests/Project.toml | 1 + test/TryTests/src/test_base.jl | 5 ++- test/TryTests/src/test_tools.jl | 5 ++- test/runtests.jl | 2 +- 15 files changed, 140 insertions(+), 49 deletions(-) create mode 100644 lib/TryExperimental/LICENSE create mode 100644 lib/TryExperimental/Project.toml create mode 100644 lib/TryExperimental/README.md create mode 100644 lib/TryExperimental/src/TryExperimental.jl rename {src => lib/TryExperimental/src}/base.jl (100%) create mode 100644 lib/TryExperimental/src/prelude.jl create mode 100644 lib/TryExperimental/test/Project.toml create mode 100644 lib/TryExperimental/test/runtests.jl diff --git a/README.md b/README.md index 84ec238..1370dd1 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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)); @@ -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 @@ -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 @@ -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 diff --git a/examples/inferrability.jl b/examples/inferrability.jl index 8282e18..3e3f6c1 100644 --- a/examples/inferrability.jl +++ b/examples/inferrability.jl @@ -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) diff --git a/lib/TryExperimental/LICENSE b/lib/TryExperimental/LICENSE new file mode 100644 index 0000000..02e1d79 --- /dev/null +++ b/lib/TryExperimental/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Takafumi Arakaki 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. diff --git a/lib/TryExperimental/Project.toml b/lib/TryExperimental/Project.toml new file mode 100644 index 0000000..203b72f --- /dev/null +++ b/lib/TryExperimental/Project.toml @@ -0,0 +1,10 @@ +name = "TryExperimental" +uuid = "ae3b139e-64da-4858-8f55-5617df0d650e" +authors = ["Takafumi Arakaki and contributors"] +version = "0.1.0-DEV" + +[deps] +Try = "bf1d0ff0-c4a9-496b-85f0-2b0d71c4f32a" + +[compat] +julia = "1.6" diff --git a/lib/TryExperimental/README.md b/lib/TryExperimental/README.md new file mode 100644 index 0000000..2913a9a --- /dev/null +++ b/lib/TryExperimental/README.md @@ -0,0 +1 @@ +# TryExperimental diff --git a/lib/TryExperimental/src/TryExperimental.jl b/lib/TryExperimental/src/TryExperimental.jl new file mode 100644 index 0000000..7506b6b --- /dev/null +++ b/lib/TryExperimental/src/TryExperimental.jl @@ -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 diff --git a/src/base.jl b/lib/TryExperimental/src/base.jl similarity index 100% rename from src/base.jl rename to lib/TryExperimental/src/base.jl diff --git a/lib/TryExperimental/src/prelude.jl b/lib/TryExperimental/src/prelude.jl new file mode 100644 index 0000000..e43d905 --- /dev/null +++ b/lib/TryExperimental/src/prelude.jl @@ -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 diff --git a/lib/TryExperimental/test/Project.toml b/lib/TryExperimental/test/Project.toml new file mode 100644 index 0000000..8d51fe4 --- /dev/null +++ b/lib/TryExperimental/test/Project.toml @@ -0,0 +1,3 @@ +[deps] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TestFunctionRunner = "792026f5-ac9a-4a19-adcb-47b0ce2deb5d" diff --git a/lib/TryExperimental/test/runtests.jl b/lib/TryExperimental/test/runtests.jl new file mode 100644 index 0000000..d358b79 --- /dev/null +++ b/lib/TryExperimental/test/runtests.jl @@ -0,0 +1,2 @@ +using TestFunctionRunner +TestFunctionRunner.@run diff --git a/src/Try.jl b/src/Try.jl index 37c4e40..030bbde 100644 --- a/src/Try.jl +++ b/src/Try.jl @@ -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 diff --git a/test/TryTests/Project.toml b/test/TryTests/Project.toml index 220bf53..78091c0 100644 --- a/test/TryTests/Project.toml +++ b/test/TryTests/Project.toml @@ -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" diff --git a/test/TryTests/src/test_base.jl b/test/TryTests/src/test_base.jl index 77cafaf..d06fcee 100644 --- a/test/TryTests/src/test_base.jl +++ b/test/TryTests/src/test_base.jl @@ -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 diff --git a/test/TryTests/src/test_tools.jl b/test/TryTests/src/test_tools.jl index a8ff696..14555b3 100644 --- a/test/TryTests/src/test_tools.jl +++ b/test/TryTests/src/test_tools.jl @@ -1,7 +1,10 @@ module TestTools using Test -using Try + +import TryExperimental +const Try = TryExperimental +using .Try function test_curry() value = diff --git a/test/runtests.jl b/test/runtests.jl index d358b79..e31ace7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,2 +1,2 @@ using TestFunctionRunner -TestFunctionRunner.@run +TestFunctionRunner.@run(paths = ["../lib/TryExperimental"])