    "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);