"Produces the [[stream|Iterable]] that results from repeated 
 application of the given [[function|next]] to the given 
 [[first]] element of the stream. The stream is infinite.
 For example:
     loop(0, 2.plus).takeWhile(10.largerThan)
 produces the stream `{ 0, 2, 4, 6, 8 }`."
shared {Element+} loop<Element>(
        "The first element of the resulting stream."
        Element first,
        "The function that produces the next element of the
         stream, given the current element."
        Element next(Element element)) {
    value start = first;
    object iterable satisfies {Element+} {
        first => start;
        empty => false;
        shared actual Nothing size {
            "stream is infinite"
        function nextElement(Element element) => next(element);
        shared actual Iterator<Element> iterator() {
            variable Element current = start;
            object iterator satisfies Iterator<Element> {
                shared actual Element|Finished next() {
                    Element result = current;
                    current = nextElement(current);
                    return result;
            return iterator;
    return iterable;