Skip to content

Index conversions are too darn complicated #23822

@mbauman

Description

@mbauman

I'm entirely at fault for this one, but as a public and documented interface we're fairly constrained in the non-breaking changes we can make. There are two functions and four (!!) levels of indirection here, making things particularly hard to reason about.

  • to_indices(A, I::Tuple) — the main entry point. Note that I is a tuple — not a vararg. This is different from nearly all of our other indexing functions.
    • At this point, simple indices that only contain Integers get converted straight away (since calling indices(A) is expensive in some cases)
  • to_indices(A, indices(A), I::Tuple) — this is the general form, it recurses through the two types of indices in sync.
    • At this point, multidimensional indices are expanded since they need to walk through multiple dimensions of the parent
    • Also indices like : that need access to the parent's indices in order to expand
  • Base.to_index(A::Specialized, I[1]) — for each element of the tuple of passed indices that makes it this far, we allow arrays to specialize their behaviors.
  • Base.to_index(I[1]) — and, finally, we allow the index itself to implement a conversion.

Note that Base.to_index is not exported but it's documented as a function you can specialize.

I think we should simplify this for 1.0. The reasons for this design are largely historical, but some of these are still true:

  • We used to need to support partial linear indexing, which made the indices(A) computation hard for final :s.
  • Ambiguities used to be a PITA. Now I think you'd want to know when there's a conflict and your specialization may not take effect.
  • Walking through indices(A) and I together isn't trivial — you need to use something like Base._maybe_tail and such. Unlike the other two, I don't have a good solution for this one, and it makes documenting how to do this very complicated.

Not sure about the best way to resolve this (or if it's even worth futzing about), but I figured I'd open an issue to see what others think.

Metadata

Metadata

Assignees

Labels

arrays[a, r, r, a, y, s]

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions