| "Abstraction of [[ordinal types|Ordinal]] whose values may |
| be used as endpoints of a [[span]] or [[measure]]. |
| |
| An `Enumerable` type is characterized by each element |
| having well-defined [[offset]] and [[neighbour]] functions. |
| Given an instance `x` of an enumerable type `X`: |
| |
| - for any integer-valued offset, there is a unique |
| _neighbour_ `y` of `X` with that offset, and |
| - if `y` is an instance of `X`, then there is a |
| well-defined integer-valued _offset_ of `x` from `y`. |
| |
| The offset function must satisfy: |
| |
| - `x.offset(x) == 0`, and |
| - `x.successor.offset(x) == 1` if `x!=x.successor`. |
| |
| The neighbour function must satisfy: |
| |
| - `x.neighbour(0) == x`, |
| - `x.neighbour(n-1) == x.neighbour(n).predecessor`, and |
| - `x.neighbour(n+1) == x.neighbour(n).successor`. |
| |
| Of course, it follows that: |
| |
| - `x.neighbour(-1) == x.predecessor`, and |
| - `x.neighbour(1) == x.successor`. |
| |
| An enumerable type may be _linear_ or _recursive_. If `X` |
| is a linear enumerable type, then the offset function |
| satisfies: |
| |
| - `x.predecessor.offset(x) == -1` if `x!=x.predecessor`, |
| - `x.offset(y) == -y.offset(x)` for any instance `y` of `X`, |
| and |
| - `x.offset(y) == x.offset(z) + z.offset(y)`. |
| |
| Otherwise, `X` is a recursive enumerable type with a finite |
| list of enumerated instances of size `count`, and its |
| offset and neighbour functions must satisfy: |
| |
| - `x.neighbour(count)==x`, |
| - `x.offset(y) >= 0` for any instance `y` of `X`, and |
| - `x.predecessor.offset(x) == count - 1`. |
| |
| A range of values of an enumerable type may be specified |
| using: |
| |
| - the _span operator_, written `first..last`, or |
| - the _segment operator_, written `first:length`." |
| see (`class Range`, |
| `function span`, `function measure`) |
| shared interface Enumerable<Other> of Other |
| satisfies Ordinal<Other> |
| given Other satisfies Enumerable<Other> { |
| |
| "The indirect successor or predecessor at the given |
| [[offset]], where: |
| |
| - `x.neighbour(0) == x`, |
| - `x.neighbour(i+1) == x.neighbour(i).successor`, and |
| - `x.neighbour(i-1) == x.neighbour(i).predecessor`." |
| throws (`class OverflowException`, |
| "if the neighbour cannot be represented as an |
| instance of the type") |
| since("1.1.0") |
| shared formal Other neighbour(Integer offset); |
| |
| shared actual default Other successor => neighbour(1); |
| shared actual default Other predecessor => neighbour(-1); |
| |
| "Compute the offset from the given value, where: |
| |
| - `x.offset(x) == 0`, and |
| - `x.successor.offset(x) == 1` if `x!=x.successor`." |
| throws (`class OverflowException`, |
| "if the offset cannot be represented as an |
| integer") |
| since("1.1.0") |
| shared formal Integer offset(Other other); |
| |
| "The sign of the offset from the given value." |
| since("1.1.0") |
| shared default Integer offsetSign(Other other) |
| => offset(other).sign; |
| |
| } |
| |