Iterator

An iterator is an object used to retrieve elements of a container.

for! 0..9, i =>
    print! i

This code prints the numbers 0 through 9. Each number (=Int object) is assigned to i and the following operation (=print! i) is executed. This kind of repetitive execution is called iteration.

Now let's look at the type signature of the for! procedure.

for!: |T: Type, I <: Iterable T| (I, T => None) => None

The first argument seems to accept an object of type Iterable.

Iterable is a type with .Iterator attribute, .iter method in the request method.

Iterable T = Trait {
    .Iterator = {Iterator}
    .iter = (self: Self) -> Self.Iterator T
}

The type {Iterator} of the .Iterator attribute is so-called set-kind (kind is described here).

assert [1, 2, 3] in Iterable(Int)
assert 1..3 in Iterable(Int)
assert [1, 2, 3].Iterator == ArrayIterator
assert (1..3).Iterator == RangeIterator

log [1, 2, 3].iter() # <ArrayIterator object
log (1..3).iter() # <RangeIterator object>

Both ArrayIterator and RangeIterator are classes that implement Iterator and exist only to give Array and Range iteration functions. Such a design pattern is called companion class 1. And the IteratorImpl patch is the core of the iteration functionality. Iterator requires only one .next method, IteratorImpl provides dozens of methods indeed. ArrayIterator and RangeIterator can use the implementation method of IteratorImpl just by implementing the .next method. For this convenience, the standard library implements a number of iterators.

classDiagram
    class Array~T~ {
        ...
        iter() ArrayIterator~T~
    }
    class Range~T~ {
        ...
        iter() RangeIterator~T~
    }
    class Iterable~T~ {
        <<trait>>
        iter() Iterator~T~
    }
    Iterable~T~ <|.. Array~T~: Impl
    Iterable~T~ <|.. Range~T~: Impl
    class ArrayIterator~T~ {
        array: Array~T~
        next() T
    }
    class RangeIterator~T~ {
        range: Range~T~
        next() T
    }
    class Iterator~T~ {
        <<trait>>
        next() T
    }
    Iterator~T~ <|.. ArrayIterator~T~: Impl
    Iterator~T~ <|.. RangeIterator~T~: Impl

    Array <-- ArrayIterator
    Range <-- RangeIterator

Types such as Iterable that provide an interface for handling traits (in this case Iterator) in a static dispatch yet unified manner are called companion class adapters.


1 There doesn't seem to be a uniform name for this pattern, but in Rust, there is [companion struct pattern]( https://gist.github.com/qnighy/be99c2ece6f3f4b1248608a04e104b38# :~:text=%E3%82%8F%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%80%82-,companion%20struct,-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A8%E3%80%81%E3 %81%9D%E3%81%AE), and was named after it.