Implementing the AbstractArray interface


#1

First of all, I’m still running v0.6.4 (-_-).

I’m specifically trying to write a subtype of AbstractArray with a non-standard data structure backing it. I’d like to override getindex specifically in the case of slices (e.g., index varargs containing either single integers or Colons), but I’m not sure what signature of getindex/setindex! I need to override.

base/abstractarray.jl says:

## Approach:
# We only define one fallback method on getindex for all argument types.
# That dispatches to an (inlined) internal _getindex function, where the goal is
# to transform the indices such that we can call the only getindex method that
# we require the type A{T,N} <: AbstractArray{T,N} to define; either:
#       getindex(::A, ::Int) # if IndexStyle(A) == IndexLinear() OR
#       getindex{T,N}(::A{T,N}, ::Vararg{Int, N}) # if IndexCartesian()
# If the subtype hasn't defined the required method, it falls back to the
# _getindex function again where an error is thrown to prevent stack overflows.

But supplying the second method only seems to net me scalar indexing. I’d even like full non-scalar multidimensional indexing.

I looked at StaticArrays.jl as well, but their getindex/setindex! functions are generated which has the side-effect of making it harder for me to read.

If someone could point me in the right direction, I’d greatly appreciate it.

EDIT: Just in case it’s unclear, I’d like the non-scalar getindex to return a CustomArray as well. The data structure stores some bookkeeping that I’d like to persist across slices.


#2

That comment is describing the strategy on how we implement the backbone architecture that supports the AbstractArray interface, not how users should extend it themselves.

Have you read https://docs.julialang.org/en/v0.6.4/manual/interfaces/#man-interface-array-1 ?


#3

Yes; it tells me to override getindex(A, I...). I don’t understand what the type of I is there.


#4

The only methods that are required to get your array working (in a bare-bones manner) are getindex with Int index(es) and size (see the required methods section of that table). Everything beyond that is optional customization. You can also completely customize getindex(A::CustomArray, I::Any...) (so it’s an optional method to override) but of course then you’re on your own in implementing all the indexing behaviors we support. So there are the other optional methods that can help you tweak things here and there.

The tweak I think you’re looking for is similar. Check out the toy SparseArray example — I think that does what you’re looking for: it implements scalar (Int) indexing and indexed assignment and then defines similar such that non-scalar indexing returns SparseArrays instead of Array.


#5

I see. That did the trick. Thanks!