Vectors with different out-of-bounds behavior

Consider integer vectors, Ivect(n) = Vector{Int}(undef, n).

If you access a vector A = Ivect(n) with indices < 1 or > n,
a BoundsError is thrown.

How can you introduce an integer vector type that simply returns 0 in these cases?

There are in fact just two functions you must define for your struct to behave like an array:

struct Zeroed{T,N,AT} <: AbstractArray{T,N}
    data::AT
    Zeroed(data::AT) where {AT<:AbstractArray{T,N}} where {T,N} = new{T,N,AT}(data)
end
Base.size(A::Zeroed) = size(A.data)
Base.getindex(A::Zeroed, ij...) = all(in.(ij, axes(A.data))) ? 
    getindex(A.data, ij...) : zero(eltype(A))

Zeroed(rand(3,4))[3,100] == 0
1 Like

Thanks, looks good, but exceeds my understanding. It would be enough if I got something like that going:

struct Ivect <: AbstractArray
    data::Vector{Int}
    function Ivect(n::Int)
        new(Vector{Int}(undef, n))
    end
end
Base.size(A::Ivect) = size(A.data)
Base.getindex(A::Ivect, n) = (n < 1 || n > size(A)) ? Int(0) : 
getindex(A.data, n) 

A = Ivect(5); for i in 1:size(A) (A[i] = i) end
println(A[0], " ", A[end], " ", A[end+1])

This should almost work too, you need struct Ivect <: AbstractArray{Int,1} and I think you want n > length(A) in getindex. To write into the array, you also need

Base.setindex!(A::Ivect, val, i::Int) = A.data[i] = val

Then A = Ivect(3); A[1] = 33; [A[i] for i in 0:10] should work.

1 Like

Great! Thanks! Now I can start studying your first, sophisticated, solution.

You could also just use get instead, e.g.:

julia> a = [1, 2, 3]
3-element Array{Int64,1}:
 1
 2
 3

julia> get(a, 2, 0)
2

julia> get(a, 5, 0)
0

julia> get(a, -1, 0)
0
3 Likes