"A [[Range]] of adjacent [[Enumerable]] values generated by a [[first]] element, and a strictly positive [[size]]. The range includes all values whose offset from `first` is non-negative and less than the `size`." see (`class Span`, `interface Enumerable`) final class Measure<Element>(first, size) extends Range<Element>() given Element satisfies Enumerable<Element> { "The start of the range." shared actual Element first; "The size of the range." shared actual Integer size; "Can't be used for empty segments" assert (size > 0); shared actual String string => first.string + ":" + size.string; shared actual Element last => first.neighbour(size-1); "Determines if this sized range has more elements than the given [[length]]." shared actual Boolean longerThan(Integer length) => size > length; "Determines if this sized range has fewer elements than the given [[length]]." shared actual Boolean shorterThan(Integer length) => size < length; "The index of the end of the sized range." shared actual Integer lastIndex => size-1; "The rest of the range, without its first element." shared actual Element[] rest => size==1 then [] else Measure(first.successor,size-1); "The element of the range that occurs [[index]] values after the start of the range." shared actual Element? getFromFirst(Integer index) { if (index<0 || index >= size) { return null; } return first.neighbour(index); } shared actual Boolean increasing => true; shared actual Boolean decreasing => false; "An iterator for the elements of the sized range." shared actual Iterator<Element> iterator() { object iterator satisfies Iterator<Element> { variable value count = 0; variable value current = first; shared actual Element|Finished next() { if (++count>size) { return finished; } else { return current++; } } string => "(``outer.string``).iterator()"; } return iterator; } shared actual {Element+} by(Integer step) { "step size must be greater than zero" assert (step > 0); return step == 1 then this else By(step); } class By(Integer step) satisfies {Element+} { size => 1 + (outer.size - 1) / step; first => outer.first; string => "(``outer.string`` by ``step``)"; shared actual Iterator<Element> iterator() { object iterator satisfies Iterator<Element> { variable value count = 0; variable value current = first; shared actual Element|Finished next() { if (++count>size) { return finished; } else { value result = current; current = current.neighbour(step); return result; } } string => "``outer.string``.iterator()"; } return iterator; } } shared actual Measure<Element> shifted(Integer shift) { if (shift==0) { return this; } else { return Measure(first.neighbour(shift),size); } } "Determines if this range includes the given object." shared actual Boolean contains(Object element) { if (is Element element) { return containsElement(element); } else { return false; } } "Determines if this range includes the given value." shared actual Boolean occurs(Anything element) { if (is Element element) { return containsElement(element); } else { return false; } } shared actual Boolean containsElement(Element x) => 0 <= x.offset(first) < size; shared actual Boolean includes(List<Anything> sublist) { if (sublist.empty) { return true; } else if (is Range<Element> sublist) { return includesRange(sublist); } else { return super.includes(sublist); } } shared actual Boolean includesRange(Range<Element> sublist) { switch (sublist) case (is Measure<Element>) { value offset = sublist.first.offset(first); return offset >= 0 && offset + sublist.size <= size; } case (is Span<Element>) { if (sublist.decreasing) { return false; } else { value offset = sublist.first.offset(first); return offset >= 0 && offset + sublist.size <= size; } } } shared actual Boolean equals(Object that) { if (is Measure<Object> that) { //optimize for another Measure return that.size==size && that.first==first; } else if (is Span<Object> that) { return that.increasing && that.first == first && that.size == size; } else { //it might be another sort of List return super.equals(that); } } shared actual Element[] measure(Integer from, Integer length) { if (length<=0) { return []; } else { value len = from+length < size then length else size-from; return Measure(first.neighbour(from),len); } } shared actual Element[] span(Integer from, Integer to) { if (from<=to) { if (to<0 || from>=size) { return []; } else { value len = to < size then to-from+1 else size-from; return Measure(first.neighbour(from),len); } } else { if (from<0 || to>=size) { return []; } else { value len = from < size then from-to+1 else size-to; return Measure(first.neighbour(to),len).reversed; } } } shared actual Element[] spanFrom(Integer from) { if (from <= 0) { return this; } else if (from < size) { return Measure(first.neighbour(from),size-from); } else { return []; } } shared actual Element[] spanTo(Integer to) { if (to<0) { return []; } else if (to < size-1) { return Measure(first,to); } else { return this; } } } "Produces a [[Range]] of adjacent [[Enumerable]] values generated by a [[first]] element, and a strictly positive [[size]], or returns the [[empty sequence|empty]] if `size <= 0`. The range includes all values whose offset from `first` is non-negative and less than the `size`. More precisely, if `x` and `first` are of `Enumerable` type `X`, and `size` is an integer, then `x in first:size` if and only if `0 <= x.offset(first) < size`. The _measure operator_ `:` is an abbreviation for `measure()`: for (i in start:size) { ... } for (char in '0':10) { ... } The measure operator accepts the first index and size of the range: 0:5 // [0, 1, 2, 3, 4] If the size is nonpositive, the range is empty: 0:0 // [] 5:0 // [] 0:-5 // []" shared Range<Element>|[] measure<Element> (Element first, Integer size) given Element satisfies Enumerable<Element> => size <= 0 then [] else Measure(first, size);