From 78bba1021ad387ca361ccbe0c3491ea3b08bb024 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Sat, 19 Jun 2021 11:44:14 -0400 Subject: [PATCH] Methods for `get` (#744) --- Project.toml | 2 +- README.md | 4 ++++ src/Compat.jl | 20 +++++++++++++++++++ test/runtests.jl | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 5092db818..f377285a4 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Compat" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "3.30.0" +version = "3.31.0" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" diff --git a/README.md b/README.md index a8efb5c1a..1512d5f5c 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ changes in `julia`. ## Supported features +* `get` accepts tuples and numbers ([#41007], [#41032]) (since Compat 3.31) + * `muladd(A,B,z)` now accepts arrays ([#37065]) (since Compat 3.30) * `@something` and `@coalesce` as short-circuiting versions of `something` and `coalesce` ([#40729]) (since Compat 3.29) @@ -248,3 +250,5 @@ Note that you should specify the correct minimum version for `Compat` in the [#37454]: https://github.com/JuliaLang/julia/pull/37454 [#40729]: https://github.com/JuliaLang/julia/pull/40729 [#37065]: https://github.com/JuliaLang/julia/pull/37065 +[#41007]: https://github.com/JuliaLang/julia/pull/41007 +[#41032]: https://github.com/JuliaLang/julia/pull/41032 diff --git a/src/Compat.jl b/src/Compat.jl index 27f004dba..95f978845 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -1012,6 +1012,26 @@ if VERSION < v"1.7.0-DEV.1088" export @something, @coalesce end +import Base: get, Dims, Callable + +# https://github.com/JuliaLang/julia/pull/41007 +if VERSION < v"1.7.0-DEV.1220" + get(f::Callable, A::AbstractArray, i::Integer) = checkbounds(Bool, A, i) ? A[i] : f() + get(f::Callable, A::AbstractArray, I::Tuple{}) = checkbounds(Bool, A) ? A[] : f() + get(f::Callable, A::AbstractArray, I::Dims) = checkbounds(Bool, A, I...) ? A[I...] : f() + + get(t::Tuple, i::Integer, default) = i in 1:length(t) ? getindex(t, i) : default + get(f::Callable, t::Tuple, i::Integer) = i in 1:length(t) ? getindex(t, i) : f() +end + +# https://github.com/JuliaLang/julia/pull/41032 +if VERSION < v"1.7.0-DEV.1230" + get(x::Number, i::Integer, default) = isone(i) ? x : default + get(x::Number, ind::Tuple, default) = all(isone, ind) ? x : default + get(f::Callable, x::Number, i::Integer) = isone(i) ? x : f() + get(f::Callable, x::Number, ind::Tuple) = all(isone, ind) ? x : f() +end + include("iterators.jl") include("deprecated.jl") diff --git a/test/runtests.jl b/test/runtests.jl index 3a5ce387e..13fe0926f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1016,3 +1016,54 @@ end @test @coalesce(1, error("failed")) === 1 @test_throws ErrorException @coalesce(missing, error("failed")) end + +@testset "get" begin + A = reshape([1:24...], 4, 3, 2) + B = reshape([1:24...], 4, 3, 2) + + global c = 0 + f() = (global c = c+1; 0) + @test get(f, A, ()) == 0 + @test c == 1 + @test get(f, B, ()) == 0 + @test c == 2 + @test get(f, A, (1,)) == get(f, A, 1) == A[1] == 1 + @test c == 2 + @test get(f, B, (1,)) == get(f, B, 1) == B[1] == 1 + @test c == 2 + @test get(f, A, (25,)) == get(f, A, 25) == 0 + @test c == 4 + @test get(f, B, (25,)) == get(f, B, 25) == 0 + @test c == 6 + @test get(f, A, (1,1,1)) == A[1,1,1] == 1 + @test get(f, B, (1,1,1)) == B[1,1,1] == 1 + @test get(f, A, (1,1,3)) == 0 + @test c == 7 + @test get(f, B, (1,1,3)) == 0 + @test c == 8 + @test get(f, TSlow([]), ()) == 0 + @test c == 9 + + @test get((5, 6, 7), 1, 0) == 5 + @test get((), 5, 0) == 0 + @test get((1,), 3, 0) == 0 + @test get(()->0, (5, 6, 7), 1) == 5 + @test get(()->0, (), 4) == 0 + @test get(()->0, (1,), 3) == 0 + + for x in [1.23, 7, ℯ, 4//5] #[FP, Int, Irrational, Rat] + @test get(x, 1, 99) == x + @test get(x, (), 99) == x + @test get(x, (1,), 99) == x + @test get(x, 2, 99) == 99 + @test get(x, 0, pi) == pi + @test get(x, (1,2), pi) == pi + c = Ref(0) + @test get(() -> c[]+=1, x, 1) == x + @test get(() -> c[]+=1, x, ()) == x + @test get(() -> c[]+=1, x, (1,1,1)) == x + @test get(() -> c[]+=1, x, 2) == 1 + @test get(() -> c[]+=1, x, -1) == 2 + @test get(() -> c[]+=1, x, (3,2,1)) == 3 + end +end