Iterators

The Iter.mo module provides useful classes and public functions for iteration on data sequences.

An iterator in Motoko is an object with a single method next. Calling next returns a ?T where T is the type over which we are iterating. An Iter object is consumed by calling its next function until it returns null.

We can make an Iter<T> from any data sequence. Most data sequences in Motoko, like Array, List and Buffer provide functions to make an Iter<T>, which can be used to iterate over their values.

The type Iter<T> is an object type with one single function:

type Iter<T> = { next : () -> ?T }

The next function takes no arguments and returns ?T where T is the type of the value being iterated over.

Example

import Array "mo:base/Array";

let a : [Nat] = [1, 2, 3];
let iter = Array.vals(a);

assert(?1 == iter.next());
assert(?2 == iter.next());
assert(?3 == iter.next());
assert(null == iter.next());

We use the vals function from the Array.mo module to make an Iter<Nat> from our array. We call its next function three times. After that the iterator is consumed and returns null.

Import

The convention is to name the module alias after the file name it is defined in:

import Iter "mo:base/Iter";

Ranges

This module includes two classes range and revRange to make ranges (and reversed ranges) of Nat or Int respectively. Ranges may be used in a for loop:

import Iter "mo:base/Iter";

for (i in Iter.range(0,4)) {
  // do something 5 times
};

for (i in Iter.revRange(4,0)) {
  // do something 5 times
};

We use the in keyword to iterate over the Iter<Nat> and bind the values to i in a for loop. The second for loop iterates over a Iter<Int>.

On this page

Class range

    Function next

Class revRange

    Function next

Function iterate
Function size
Function map
Function filter
Function make
Function fromArray
Function fromArrayMut
Function fromList
Function toArray
Function toArrayMut
Function toList
Function sort

Class range

class range(x : Nat, y : Int)

range.next

func next() : ?Nat
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

let num1 = myRange.next(); // returns 1
let num2 = myRange.next(); // returns 2
let num3 = myRange.next(); // returns 3
let num4 = myRange.next(); // returns null

Class revRange

class revRange(x : Int, y : Int)

revRange.next

func next() : ?Int
import Iter "mo:base/Iter";

let myRevRange = Iter.revRange(5, 8);

let number1 = myRevRange.next(); // returns 8
let number2 = myRevRange.next(); // returns 7
let number3 = myRevRange.next(); // returns 6
let number4 = myRevRange.next(); // returns 5
let number5 = myRevRange.next(); // returns null

Iter.iterate

func iterate<A>(

  xs : Iter<A>,
   f : (A, Nat) -> ()

) : ()
Parameters
Generic parametersA
Variable argumentxs : Iter<A>
Function argumentf : (A, Nat) -> ()
Return type()
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

var sum = 0;

func update(a : Nat, b : Nat) {
    sum += a;
};

Iter.iterate(myRange, update);

Iter.size

func size<A>(xs : Iter<A>) : Nat
Parameters
Generic parametersA
Variable argumentxs : Iter<A>
Return typeNat
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

Iter.size(myRange);

Iter.map

func map<A, B>(

  xs : Iter<A>,
   f : A -> B

) : Iter<B>
Parameters
Generic parameterA, B
Variable argumentxs : Iter<A>
Function argumentf : A -> B
Return typeIter<B>
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

func change(n : Nat) : Int {
    n * -1;
};

let mapedIter = Iter.map<Nat, Int>(myRange, change);

Iter.toArray(mapedIter);

Iter.filter

func filter<A>(

  xs : Iter<A>,
   f : A -> Bool

) : Iter<A>
Parameters
Generic parametersA
Variable argumentxs : Iter<A>
Function argumentf : A -> Bool
Return typeIter<A>
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

func change(n : Nat) : Bool {
    n > 1;
};

let filterIter = Iter.filter<Nat>(myRange, change);

Iter.toArray(filterIter);

Iter.make

func make<A>(x : A) : Iter<A>
Parameters
Generic parametersA
Variable argumentx : A
Return typeIter<A>
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.make(3);

assert (?3 == myRange.next());
assert (?3 == myRange.next());
assert (?3 == myRange.next());
//......

Iter.fromArray

func fromArray<A>(xs : [A]) : Iter<A>
Parameters
Generic parametersA
Variable argumentxs : [A]
Return typeIter<A>
import Iter "mo:base/Iter";

let array = ["bitcoin", "ETH", "ICP"];

let myRange : Iter.Iter<Text> = Iter.fromArray(array);

Iter.size(myRange);

Iter.fromArrayMut

func fromArrayMut<A>(xs : [var A]) : Iter<A>
Parameters
Generic parametersA
Variable argumentxs : [var A]
Return typeIter<A>
import Iter "mo:base/Iter";

let array = [var "bitcoin", "ETH", "ICP"];

let iter = Iter.fromArrayMut(array);

Iter.size(iter);

Iter.fromList

func fromList(xs : List<T>) : Iter
Parameters
Variable argumentxs : List<T>
Return typeIter
import List "mo:base/List";
import Iter "mo:base/Iter";

let list : List.List<Nat> = ?(0, ?(1, null));

let iter = Iter.fromList(list);

Iter.toArray(iter);

Iter.toArray

func toArray<A>(xs : Iter<A>) : [A]
Parameters
Generic parametersA
Variable argumentxs : Iter<A>
Return type[A]
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

Iter.toArray<Nat>(myRange);

Iter.toArrayMut

func toArrayMut<A>(xs : Iter<A>) : [var A]
Parameters
Generic parametersA
Variable argumentxs : Iter<A>
Return type[var A]
import Iter "mo:base/Iter";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

Iter.toArrayMut<Nat>(myRange);

Iter.toList

func list<A>(xs : Iter<A>) : List.List<A>
Parameters
Generic parametersA
Variable argumentxs : Iter<A>
Return typeList.List<A>
import Iter "mo:base/Iter";
import List "mo:base/List";

let myRange : Iter.Iter<Nat> = Iter.range(1, 3);

let list : List.List<Nat> = Iter.toList(myRange);

List.last(list);

Iter.sort

func sort<A>(

     xs : Iter<A>,
compare : (A, A) -> Order.Order

) : Iter<A>
Parameters
Generic parametersA
Variable argumentxs : Iter<A>
Function argumentcompare : (A, A) -> Order.Order
Return typeIter<A>
import Iter "mo:base/Iter";
import Int "mo:base/Int";

let a : [Int] = [5, 2, -3, 1];

let i : Iter.Iter<Int> = a.vals();

let sorted : Iter.Iter<Int> = Iter.sort(i, Int.compare);

Iter.toArray(sorted)