17883, "bradcray", "Proposal for modestly redefining '.indices' on arrays", "2021-06-07T23:10:00Z"

As of PR #15039 or so, we added .indices queries to most indexable types as a means of writing code for them that refers to their indices abstractly rather than assuming the indices are, say, 1..size or 0..<size. At that time, .indices became a synonym for .domain for arrays. Issue #15103 proposed that we retire .domain in favor of .indices on arrays, but was received fairly negatively.

[For historical purposes, this issue captures a fork in the discussion of #15103 that started at this point ]

This issue proposes another way to remove the redundancy: What if, rather than returning the array's actual domain, this query returned (or perhaps yielded in some cases?) the array's index set locally. For example, for an n x n Block-distributed array named B, B.domain would return a (const) reference to B's actual Block-distributed domain as it does today, whereas B.indices would return {1..n, 1..n} (or {0..<n, 0..<n} or whatever indices B.domain had) as a local default rectangular domain.

This would have the benefits of:

providing a data-structure neutral way of getting a local copy of the indices of the data structure in question

removing the "two ways of doing the exact same thing" case that we have today in which .domain and .indices do the same thing

providing a user-facing way to ask for B's index set without getting a block-distributed thing back or querying on a per-dimension basisâthe only two ways we can do so today I believe.

An obvious disadvantage would be:

.indices vs. .domain are similar, so learning to distinguish them is subtle and could have a significant performance impact when making the wrong choice (e.g., var A: [B.indices] real; vs. var A: [B.domain] real; or forall i in B.indices vs. forall i in B.domain).

One open question is whether .indices would have to return the indices in a closed form (say as a sparse domain for a sparse array or an associative domain for an associative array) or whether it would be reasonable for it to be implemented in a closed form in some cases (say, when the storage required is O(1), as for dense rectangular arrays) but as an iterator in others (say, when it's not, as for sparse / associative arrays).