New Issue: Design: what should 'domain.shape' do?

17909, "vasslitvinov", "Design: what should 'domain.shape' do?", "2021-06-11T04:37:10Z"

Related: .indices #15103 #17883; dims() method on rectangular domains

Background: domain.shape returns a tuple of integers indicating sizes in each dimension. For non-rectangular domains, it is a 1-tuple containing domain.size. At the same time we have considered using the term "shape" to describe the underlying index set of an iterator or an iterable expression (when such index set naturally exists).

Consideration: this follows numpy, which is a good precedent. However, if numpy arrays are 0-based, this can be considered an encoding of ranges in each dimension.

This issue proposes:

  • .shape stays as-is for dense rectangular
    • .indices or .dims() is/are the things that talk about ranges
    • this supports the rule "if shapes of two domains are equal, they can be assigned/zippered/etc."
  • shape is not defined for associative domains, as they are not really "shapeful"; so, use .size instead
  • shape on a sparse domain gives same thing as its parent domain
    • the logical shape for a sparse rectangular
    • not defined for a sparse associative
  • use .domain to get the shape of an iterator/an iterable, by analogy to arrays
    • for some iterators, "shape" is not defined, ex. an iterator performing a recursive traversal of a tree
    • for some iterators, the "shape" is a range, ex. a for-expression over a range
    • so user code might look like:
if d.hasDomain() {
  // use d.domain
} else if d.hasRange() {
  // use d.range
} else {
  // do something without relying on the iterator's shape
}