Skip to content

Commit

Permalink
Adds some documentation to the Iter module
Browse files Browse the repository at this point in the history
  • Loading branch information
kritzcreek committed Jun 22, 2020
1 parent 5f0829f commit e9751cb
Showing 1 changed file with 66 additions and 4 deletions.
70 changes: 66 additions & 4 deletions src/Iter.mo
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,45 @@ import Array "Array";
import List "List";

module {
public type Iter<T> = {next : () -> ?T};
/// An iterator that produces values of type `T`. Calling `next` returns
/// `null` when iteration is finished.
///
/// Iterators are inherently stateful. Calling `next` "consumes" a value from
/// the Iterator that cannot be put back, so keep that in mind when sharing
/// iterators between consumers.
public type Iter<T> = { next : () -> ?T };

/// Creates an iterator that produces all `Nat`'s from `x` to `y` including
/// both of the bounds.
/// ```
/// let iter = range(1, 3);
/// assertEqual(?1, iter.next());
/// assertEqual(?2, iter.next());
/// assertEqual(?3, iter.next());
/// assertEqual(null, iter.next());
/// ```
public class range(x : Nat, y : Int) {
var i = x;
public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} };
};

/// Like [`range`](#value.range) but produces the values in the opposite
/// order.
public class revRange(x : Int, y : Int) {
var i = x;
public func next() : ?Int { if (i < y) null else {let j = i; i -= 1; ?j} };
};

/// Calls a function `f` on every value produced by an iterator and discards
/// the results. If you're looking to keep these results use
/// [`transform`](#value.transform).
/// ```
/// var sum = 0;
/// apply(range(1, 3), func(x : Nat) {
/// sum += x;
/// });
/// assertEquals(6, sum)
/// ```
public func apply<A>(
xs : Iter<A>,
f : (A, Nat) -> ()
Expand All @@ -35,14 +62,25 @@ module {
};
};

func size<A>(xs : Iter<A>) : Nat {
/// Consumes an iterator and counts how many elements were produced
/// (discarding them in the process).
public func size<A>(xs : Iter<A>) : Nat {
var len = 0;
apply<A>(xs, func (x, i) { len += 1; });
len;
};

/// Takes a function and an iterator and creates a new iterator by applying
/// the function to every element produced by the old iterator.
/// ```
/// let iter = range(1, 3);
/// let transformedIter = transform(iter, func (x : Nat) : Nat { x * 2 });
/// assertEqual(?2, transformedIter.next());
/// assertEqual(?4, transformedIter.next());
/// assertEqual(?6, transformedIter.next());
/// assertEqual(null, transformedIter.next());
/// ```
public func transform<A, B>(xs : Iter<A>, f : A -> B) : Iter<B> = object {
var i = 0;
public func next() : ?B {
label l loop {
switch (xs.next()) {
Expand All @@ -53,19 +91,33 @@ module {
break l;
};
};
i += 1;
continue l;
};
null;
};
};

/// Creates an iterator that produces an infinite sequence of `x`.
/// ```
/// let iter = make(10);
/// assertEquals(?10, iter.next())
/// assertEquals(?10, iter.next())
/// assertEquals(?10, iter.next())
/// ```
public func make<A>(x : A) : Iter<A> = object {
public func next() : ?A {
?x;
};
};

/// Creates an iterator that produces the elements of an Array.
/// ```
/// let iter = fromArray([1, 2, 3]);
/// assertEquals(?1, iter.next())
/// assertEquals(?2, iter.next())
/// assertEquals(?3, iter.next())
/// assertEquals(null, iter.next())
/// ```
public func fromArray<A>(xs : [A]) : Iter<A> {
var ix : Nat = 0;
let size = xs.len();
Expand All @@ -82,26 +134,36 @@ module {
}
};

/// Like [`fromArray`](#value.fromArray) but for Arrays with mutable elements.
/// Captures the elements of the Array at the time the iterator is created, so
/// further modifications won't be reflected in the iterator.
public func fromArrayMut<A>(xs : [var A]) : Iter<A> {
fromArray<A>(Array.freeze<A>(xs));
};

/// Like [`fromArray`](#value.fromArray) but for Lists.
public func fromList<A>(xs : List.List<A>) : Iter<A> {
List.toArray<A>(xs).vals();
};

/// Consumes an iterator and collects its produced elements in an Array.
/// let iter = range(1, 3);
/// assertEquals([1, 2, 3], toArray(iter));
public func toArray<A>(xs : Iter<A>) : [A] {
List.toArray<A>(toList<A>(xs));
};

/// Like [`toArray`](#value.toArray) but for Arrays with mutable elements.
public func toArrayMut<A>(xs : Iter<A>) : [var A] {
Array.thaw<A>(toArray<A>(xs));
};

/// Like [`toArray`](#value.toArray) but for Lists.
public func toList<A>(xs : Iter<A>) : List.List<A> {
toListWithSize<A>(xs).list;
};

/// Deprecate?
public func toListWithSize<A>(
xs : Iter<A>,
) : ({
Expand Down

0 comments on commit e9751cb

Please sign in to comment.