I am having some trouble defining my struct as a subtype of AbstractArray.
As an example, say I want to define a Point in dim dimensional space as follows:
struct Point{dim} <: AbstractArray{Float64,dim}
x::NTuple{dim, Float64}
end
Now according to the documentation, the minimum functions I need to overload for Point to be an AbstractArray are: Base.size, Base.IndexStyle, Base.getindex and Base.setindex!
So I do it as follows:
Base.size(p::Point{dim}) where dim = (dim,)
Base.IndexStyle(::Type{<:Point}) = IndexLinear()
Base.getindex(p::Point{dim}, i::Int64) where dim = p.x[i]
Base.setindex!(p::Point{dim}, v, i::Int64) where dim = (p.x[i] = v)
If I try to initialize this struct, I get an error message that I can’t quite understand:
julia> Point((1.5,2.4))
2-element Point{2}:Error showing value of type Point{2}:
ERROR: BoundsError: attempt to access (Base.OneTo(2),)
at index [2]
Stacktrace:
[1] getindex(::Tuple{Base.OneTo{Int64}}, ::Int64) at ./tuple.jl:24
[2] axes at ./abstractarray.jl:57 [inlined]
...
I would greatly appreciate inputs on the correct way to do this.
Your trouble is stemming from the fact that you’re reporting to AbstractArray that your struct has dim dimensions when it’s only 1-dimensional. Change it to struct Point{dim} <: AbstractArray{Float64,1} and I think all should work. I’d probably rename dim to len to make it clearer.
Oh, not quite all will work: Your setindex! method will run into trouble since tuples are immutable, so if you use a tuple as your backing you need to make the strict itself mutable and replace the entire tuple when you change it.