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.
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
.
The convention is to name the module alias after the file name it is defined in:
import Iter "mo:base/Iter";
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>
.
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(x : Nat, y : Int)
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(x : Int, y : Int)
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
func iterate<A>(
xs : Iter<A>,
f : (A, Nat) -> ()
) : ()
Parameters | |
Generic parameters | A |
Variable argument | xs : Iter<A> |
Function argument | f : (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);
func size<A>(xs : Iter<A>) : Nat
Parameters | |
Generic parameters | A |
Variable argument | xs : Iter<A> |
Return type | Nat |
import Iter "mo:base/Iter";
let myRange : Iter.Iter<Nat> = Iter.range(1, 3);
Iter.size(myRange);
func map<A, B>(
xs : Iter<A>,
f : A -> B
) : Iter<B>
Parameters | |
Generic parameter | A, B |
Variable argument | xs : Iter<A> |
Function argument | f : A -> B |
Return type | Iter<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);
func filter<A>(
xs : Iter<A>,
f : A -> Bool
) : Iter<A>
Parameters | |
Generic parameters | A |
Variable argument | xs : Iter<A> |
Function argument | f : A -> Bool |
Return type | Iter<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);
func make<A>(x : A) : Iter<A>
Parameters | |
Generic parameters | A |
Variable argument | x : A |
Return type | Iter<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());
//......
func fromArray<A>(xs : [A]) : Iter<A>
Parameters | |
Generic parameters | A |
Variable argument | xs : [A] |
Return type | Iter<A> |
import Iter "mo:base/Iter";
let array = ["bitcoin", "ETH", "ICP"];
let myRange : Iter.Iter<Text> = Iter.fromArray(array);
Iter.size(myRange);
func fromArrayMut<A>(xs : [var A]) : Iter<A>
Parameters | |
Generic parameters | A |
Variable argument | xs : [var A] |
Return type | Iter<A> |
import Iter "mo:base/Iter";
let array = [var "bitcoin", "ETH", "ICP"];
let iter = Iter.fromArrayMut(array);
Iter.size(iter);
func fromList(xs : List<T>) : Iter
Parameters | |
Variable argument | xs : List<T> |
Return type | Iter |
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);
func toArray<A>(xs : Iter<A>) : [A]
Parameters | |
Generic parameters | A |
Variable argument | xs : Iter<A> |
Return type | [A] |
import Iter "mo:base/Iter";
let myRange : Iter.Iter<Nat> = Iter.range(1, 3);
Iter.toArray<Nat>(myRange);
func toArrayMut<A>(xs : Iter<A>) : [var A]
Parameters | |
Generic parameters | A |
Variable argument | xs : Iter<A> |
Return type | [var A] |
import Iter "mo:base/Iter";
let myRange : Iter.Iter<Nat> = Iter.range(1, 3);
Iter.toArrayMut<Nat>(myRange);
func list<A>(xs : Iter<A>) : List.List<A>
Parameters | |
Generic parameters | A |
Variable argument | xs : Iter<A> |
Return type | List.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);
func sort<A>(
xs : Iter<A>,
compare : (A, A) -> Order.Order
) : Iter<A>
Parameters | |
Generic parameters | A |
Variable argument | xs : Iter<A> |
Function argument | compare : (A, A) -> Order.Order |
Return type | Iter<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)