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


#1

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)

#2

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.


#3

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


#4

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


#5

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.


#6

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?


#7

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.


#8

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