Iterator Examples

Sather - A Language Tutorial
Prev | Chapter 3. Loops and Iterators | Next

# 3.3. Iterator Examples

Some of the following examples make use of arrays, which will be introduced in the chapter on Parametrized Classes

Because they are so useful, the '`while!`', '`until!`' and '`break!`' iterators are built into the language. Here's how '`while!`' could be written if it were not a primitive

    while!(pred:BOOL) is
       -- Yields as long as 'pred' is true
       loop
          if pred then
             yield;
          else
             quit;
          end;
       end;
    end;

The built-in class '`INT`' defines some useful iterators. Here's the definition of '`upto!`'. Unlike the argument '`pred`' used above, '`i`' here is declared to be '`once`'; when '`upto!`' is called, the argument is only evaluated once, the first time the iterator is called in the loop.

    upto!(once i:SAME):SAME is
       -- Yield successive integers from self to `i' inclusive.
       r ::= self;
       loop
          until!(r > i);
          yield r;
          r := r + 1
       end;
    end;

To add up the integers 1 through 10, one might say

    sum:INT := 0;
    loop
       sum := sum + 1.upto!(10);
    end;

Or, using the library iterator '`sum!`' like this. '`x`' needs to be declared (but not initialized) outside the loop, so its value is available after the loop terminates.

    x:INT;
    loop
       x := INT::sum!(1.upto!(10));
    end;

Some of the most common uses of iters are with container objects. Arrays, lists, sets, trees, strings, and vectors all have iterators to yield all their elements. Here we print all the elements of some container '`a`'

    a:ARRAY{INT} := |1,2,7|;
    loop
       #OUT + a.elt!.str + '\n';
    end;

This doubles the elements of array '`a`'

    loop
       a.set!(a.elt! * 2);
    end;

This computes the dot product of two vectors '`a`' and '`b`'. There is also a built-in method '`dot`' to do this. '`x`' needs to be declared (but not initialized) before the loop.

    loop
       x := sum!(a.elt! * b.elt!);
    end;

## Separating elements of a list

When printing out the elements of a container, or other kinds of lists, it is usually appropriate to insert a separator between all the elements (but, of course, not after the last element). There is a convenient iterator in the string class that does exactly this:.

    a:ARRAY{INT} := |1,2,3|;
    loop
       #OUT + ",".separate!(a.elt!.str);
    end;
    -- Prints out 1,2,3

The `separate!` iterator is called on the string which you wish to use to separate components of the list. In this case, the list elements will be separated by a comma. The definition of this iterator is as shown below

    class STR is
       ...
       separate!(s: STR): STR is
          -- On the first iteration just outputs `s', on later iterations
          -- it outputs self followed by `s'.
          yield s.str;
          loop
             yield self + s.str;
          end;
       end;
       ...
    end;

Note that the argument to the iterator is not a `once` argument, and will be evaluated each time the iterator is called.

Prev | Home | Next
Defining Iterators | Up | Code Inclusion and Partial Classes