Custom indexing for an AbstractVector breaks display (but not show)

Consider the following example:

julia> struct Foo <: AbstractVector{Int}
           bar :: Vector{Int}
       end
       Base.size(foo::Foo) = size(foo.bar)
       Base.getindex(foo::Foo, idx) = foo.bar[idx]
       Base.IndexStyle(::Foo) = Base.IndexLinear()

julia> Foo([1,2])
2-element Foo:
 1
 2

Life is wonderful and we have a functional AbstractVector. However, if we define the following additional method for getindex, things start to break:

julia> Base.getindex(foo::Foo, idx, jdx) = foo[idx+jdx]

julia> display(Foo([1,2])) # oops
2-element Foo:
   2   
 #undef

julia> show(Foo([1,2])) # still works
[1, 2]

I encountered this while trying to define a type that represents a vector of spherical harmonic coefficients. This object is fundamentally a vector, so I made it a subtype of AbstractVector. However, it would also be convenient to index this object using the quantum numbers l and m, hence the second getindex function. However, this breaks the display at the REPL.

Is there a way to have my cake and eat it too? Are AbstractVectors allowed to define getindex with more than one index? Why does display break, but show still work?


julia> versioninfo()
Julia Version 0.6.0-pre.beta.unknown
Commit bd84fa1 (2017-03-31 12:58 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, haswell)

Display treats vectors like matrices, and uses the same code path for both. This means it’ll index into your vector with trailing singleton dimensions.

Hm. That feels unintentional. Is there a workaround or do I need to use a different method name for the two element getindex?

Not sure if feature or bug. Both? https://github.com/JuliaLang/julia/issues/14770

To expand a bit: yes, it’s expected that N-dimensional arrays can be indexed with fewer or more than N indices. Depending on the index style you define, the fallback methods will convert to 1 or N indices with sub2ind or ind2sub. And, yes, some algorithms (beyond display) depend on this transformation.

Ok, I see. Reading through the #14770 it seems likely this behavior will change by 1.0. But for now I should just pick a different method name. Is that a fair assessment?

I’m much less certain that things will change, but I’m also against it (and an optimist).

Either way an alternate name for this behavior is your best path forward right now.

Ok, thanks for the insight! (and the awesome AbstractArray interface).