diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 88947e582fda5..92db812b249ad 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1469,6 +1469,9 @@ RangeVecIntList{A<:AbstractVector{Int}} = Union{Tuple{Vararg{Union{AbstractRange get(A::AbstractArray, i::Integer, default) = checkbounds(Bool, A, i) ? A[i] : default get(A::AbstractArray, I::Tuple{}, default) = checkbounds(Bool, A) ? A[] : default get(A::AbstractArray, I::Dims, default) = checkbounds(Bool, A, I...) ? A[I...] : default +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() function get!(X::AbstractVector{T}, A::AbstractVector, I::Union{AbstractRange,AbstractVector{Int}}, default::T) where T # 1d is not linear indexing diff --git a/base/tuple.jl b/base/tuple.jl index ad08bf42f5e1a..5ebf36b750cf0 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -32,6 +32,9 @@ getindex(t::Tuple, r::AbstractArray{<:Any,1}) = (eltype(t)[t[ri] for ri in r]... getindex(t::Tuple, b::AbstractArray{Bool,1}) = length(b) == length(t) ? getindex(t, findall(b)) : throw(BoundsError(t, b)) getindex(t::Tuple, c::Colon) = t +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() + # returns new tuple; N.B.: becomes no-op if i is out-of-bounds """ diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 9af20b8047701..05ab7147e1f7e 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -598,6 +598,31 @@ function test_get(::Type{TestAbstractArray}) @test get(TSlow([]), (), 0) == 0 @test get(TSlow([1]), (), 0) == 1 @test get(TSlow(fill(1)), (), 0) == 1 + + 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(f, TSlow([1]), ()) == 1 + @test get(f, TSlow(fill(1)), ()) == 1 end function test_cat(::Type{TestAbstractArray}) diff --git a/test/tuple.jl b/test/tuple.jl index 7c274851ea555..e8751e73b7ad4 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -179,6 +179,15 @@ end @test_throws MethodError (1,)[] @test_throws MethodError (1,1,1)[1,1] end + + @testset "get() method for Tuple (Issue #40809)" begin + @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 + end end @testset "fill to length" begin