Enumeration<A> class
An enumeration of finite parts of A.
class Enumeration<A> extends IterableBase<A> { Thunk<LazyList<Finite<A>>> thunk; Enumeration(this.thunk); factory Enumeration.empty() => new Enumeration( new Thunk(() => new LazyList.empty())); factory Enumeration.singleton(A x) => new Enumeration( new Thunk(() => new LazyList.singleton(new Finite.singleton(x)))); factory Enumeration.fix(Enumeration f(Enumeration)) { final enumeration = new Enumeration(null); final result = f(enumeration); enumeration.thunk = result.thunk; return result; } LazyList<Finite<A>> get parts => thunk.value; A operator [](int i) { var ps = parts; var it = i; while (true) { if (ps.isEmpty) throw new RangeError(i); if (it < ps.head.length) return ps.head[it]; it = it - ps.head.length; ps = ps.tail; } } Iterator<A> get iterator => parts.expand((f) => f).iterator; static LazyList<Finite> _zipPlus(LazyList<Finite> xs, LazyList<Finite> ys) => (xs.isEmpty || ys.isEmpty) ? xs + ys : new LazyList.cons(xs.head + ys.head, () => _zipPlus(xs.tail, ys.tail)); /** * Disjoint union (it is up to the user to make sure that operands are * disjoint). */ Enumeration<A> operator +(Enumeration<A> e) => new Enumeration<A>( new Thunk(() => _zipPlus(this.parts, e.parts))); /** * [Enumeration] is a functor. */ Enumeration map(f(A x)) => new Enumeration( new Thunk(() => parts.map((p) => p.map(f)))); /** * [: _reversals([1,2,3,...]) :] is [: [[1], [2,1], [3,2,1], ...] :]. */ static LazyList<LazyList> _reversals(LazyList l) { go(LazyList rev, LazyList xs) { if (xs.isEmpty) return new LazyList.empty(); final newrev = new LazyList.cons(xs.head, () => rev); return new LazyList.cons(newrev, () => go(newrev, xs.tail)); } return go(new LazyList.empty(), l); } static _prod(LazyList<Finite> xs, LazyList<LazyList<Finite>> yss) { if (xs.isEmpty || yss.isEmpty) return new LazyList.empty(); goX(ry) => xs.tail.tails().map((fs) => _conv(fs, ry)); goY(LazyList<Finite> ry, LazyList<LazyList<Finite>> rys()) { return new LazyList.cons( _conv(xs, ry), () { final _rys = rys(); return _rys.isEmpty ? goX(ry) : goY(_rys.head, () => _rys.tail); }); }; return goY(yss.head, () => yss.tail); } static _conv(LazyList<Finite> xs, LazyList<Finite> ys) { var result = new Finite.empty(); if (ys.isEmpty) return result; while(true) { if (xs.isEmpty) return result; result = result + (xs.head * ys.head); ys = ys.tail; if (ys.isEmpty) return result; xs = xs.tail; } } /** * Cartesian product. */ Enumeration<Pair> operator *(Enumeration<A> e) => new Enumeration<Pair>( new Thunk(() => _prod(this.parts, _reversals(e.parts)))); /** * [Enumeration] is an applicative functor. */ Enumeration apply(Enumeration e) => (this * e).map((pair) => (pair.fst as Function)(pair.snd)); /** * Pays for one recursive call. */ Enumeration<A> pay() => new Enumeration<A>( new Thunk(() => new LazyList.cons(new Finite.empty(), () => this.parts))); toString() => "Enum $parts"; }
Extends
IterableBase<A> > Enumeration<A>
Constructors
factory Enumeration.empty() #
factory Enumeration.empty() => new Enumeration( new Thunk(() => new LazyList.empty()));
factory Enumeration.fix(Enumeration f(Enumeration)) #
factory Enumeration.fix(Enumeration f(Enumeration)) { final enumeration = new Enumeration(null); final result = f(enumeration); enumeration.thunk = result.thunk; return result; }
Properties
final E first #
Returns the first element.
If this
is empty throws a StateError. Otherwise this method is
equivalent to this.elementAt(0)
E get first { Iterator it = iterator; if (!it.moveNext()) { throw new StateError("No elements"); } return it.current; }
final bool isEmpty #
final bool isNotEmpty #
final E last #
E get last { Iterator it = iterator; if (!it.moveNext()) { throw new StateError("No elements"); } E result; do { result = it.current; } while(it.moveNext()); return result; }
final int length #
final E single #
Returns the single element in this
.
If this
is empty or has more than one element throws a StateError.
E get single { Iterator it = iterator; if (!it.moveNext()) throw new StateError("No elements"); E result = it.current; if (it.moveNext()) throw new StateError("More than one element"); return result; }
Operators
A operator [](int i) #
A operator [](int i) { var ps = parts; var it = i; while (true) { if (ps.isEmpty) throw new RangeError(i); if (it < ps.head.length) return ps.head[it]; it = it - ps.head.length; ps = ps.tail; } }
Enumeration<A> operator +(Enumeration<A> e) #
Disjoint union (it is up to the user to make sure that operands are disjoint).
Enumeration<A> operator +(Enumeration<A> e) => new Enumeration<A>( new Thunk(() => _zipPlus(this.parts, e.parts)));
Enumeration<Pair> operator *(Enumeration<A> e) #
Cartesian product.
Enumeration<Pair> operator *(Enumeration<A> e) => new Enumeration<Pair>( new Thunk(() => _prod(this.parts, _reversals(e.parts))));
Methods
bool any(bool f(E element)) #
Enumeration apply(Enumeration e) #
Enumeration is an applicative functor.
Enumeration apply(Enumeration e) => (this * e).map((pair) => (pair.fst as Function)(pair.snd));
bool contains(Object element) #
E elementAt(int index) #
Returns the indexth element.
If this
has fewer than
index elements throws a RangeError.
Note: if this
does not have a deterministic iteration order then the
function may simply return any element without any iteration if there are
at least
index elements in this
.
E elementAt(int index) { if (index is! int || index < 0) throw new RangeError.value(index); int remaining = index; for (E element in this) { if (remaining == 0) return element; remaining--; } throw new RangeError.value(index); }
bool every(bool f(E element)) #
Iterable expand(Iterable f(E element)) #
Expands each element of this Iterable into zero or more elements.
The resulting Iterable runs through the elements returned by f for each element of this, in order.
The returned Iterable is lazy, and calls f for each element of this every time it's iterated.
Iterable expand(Iterable f(E element)) => new ExpandIterable<E, dynamic>(this, f);
dynamic firstWhere(bool test(E value), {Object orElse()}) #
Returns the first element that satisfies the given predicate test.
If none matches, the result of invoking the
orElse function is
returned. By default, when
orElse is null
, a StateError is
thrown.
dynamic firstWhere(bool test(E value), { Object orElse() }) { for (E element in this) { if (test(element)) return element; } if (orElse != null) return orElse(); throw new StateError("No matching element"); }
dynamic fold(initialValue, combine(previousValue, E element)) #
Reduces a collection to a single value by iteratively combining each element of the collection with an existing value using the provided function.
Use initialValue as the initial value, and the function combine to create a new value from the previous one and an element.
Example of calculating the sum of an iterable:
iterable.fold(0, (prev, element) => prev + element);
dynamic fold(var initialValue, dynamic combine(var previousValue, E element)) { var value = initialValue; for (E element in this) value = combine(value, element); return value; }
void forEach(void f(E element)) #
String join([String separator = ""]) #
Converts each element to a String and concatenates the strings.
Converts each element to a String by calling Object.toString on it. Then concatenates the strings, optionally separated by the separator string.
String join([String separator = ""]) { Iterator<E> iterator = this.iterator; if (!iterator.moveNext()) return ""; StringBuffer buffer = new StringBuffer(); if (separator == null || separator == "") { do { buffer.write("${iterator.current}"); } while (iterator.moveNext()); } else { buffer.write("${iterator.current}"); while (iterator.moveNext()) { buffer.write(separator); buffer.write("${iterator.current}"); } } return buffer.toString(); }
dynamic lastWhere(bool test(E value), {Object orElse()}) #
Returns the last element that satisfies the given predicate test.
If none matches, the result of invoking the
orElse function is
returned. By default, when
orElse is null
, a StateError is
thrown.
dynamic lastWhere(bool test(E value), { Object orElse() }) { E result = null; bool foundMatching = false; for (E element in this) { if (test(element)) { result = element; foundMatching = true; } } if (foundMatching) return result; if (orElse != null) return orElse(); throw new StateError("No matching element"); }
Enumeration map(f(A x)) #
Enumeration is a functor.
Enumeration map(f(A x)) => new Enumeration( new Thunk(() => parts.map((p) => p.map(f))));
Enumeration<A> pay() #
Pays for one recursive call.
Enumeration<A> pay() => new Enumeration<A>( new Thunk(() => new LazyList.cons(new Finite.empty(), () => this.parts)));
E reduce(E combine(E value, E element)) #
Reduces a collection to a single value by iteratively combining elements of the collection using the provided function.
Example of calculating the sum of an iterable:
iterable.reduce((value, element) => value + element);
E reduce(E combine(E value, E element)) { Iterator<E> iterator = this.iterator; if (!iterator.moveNext()) { throw new StateError("No elements"); } E value = iterator.current; while (iterator.moveNext()) { value = combine(value, iterator.current); } return value; }
E singleWhere(bool test(E value)) #
Returns the single element that satisfies test. If no or more than one element match then a StateError is thrown.
E singleWhere(bool test(E value)) { E result = null; bool foundMatching = false; for (E element in this) { if (test(element)) { if (foundMatching) { throw new StateError("More than one matching element"); } result = element; foundMatching = true; } } if (foundMatching) return result; throw new StateError("No matching element"); }
Iterable<E> skip(int n) #
Iterable<E> skipWhile(bool test(E value)) #
Returns an Iterable that skips elements while test is satisfied.
The filtering happens lazily. Every new Iterator of the returned
Iterable iterates over all elements of this
.
As long as the iterator's elements satisfy
test they are
discarded. Once an element does not satisfy the
test the iterator stops
testing and uses every later element unconditionally. That is, the elements
of the returned Iterable are the elements of this
starting from the
first element that does not satisfy
test.
Iterable<E> skipWhile(bool test(E value)) { return new SkipWhileIterable<E>(this, test); }
Iterable<E> take(int n) #
Iterable<E> takeWhile(bool test(E value)) #
Returns an Iterable that stops once test is not satisfied anymore.
The filtering happens lazily. Every new Iterator of the returned
Iterable starts iterating over the elements of this
.
When the iterator encounters an element e
that does not satisfy
test,
it discards e
and moves into the finished state. That is, it does not
get or provide any more elements.
Iterable<E> takeWhile(bool test(E value)) { return new TakeWhileIterable<E>(this, test); }
List<E> toList({bool growable: true}) #
Set<E> toSet() #
dynamic toString() #
Returns a string representation of this object.
toString() => "Enum $parts";
Iterable<E> where(bool f(E element)) #
Returns a lazy Iterable with all elements that satisfy the
predicate test
.
This method returns a view of the mapped elements. As long as the
returned Iterable is not iterated over, the supplied function test
will
not be invoked. Iterating will not cache results, and thus iterating
multiple times over the returned Iterable will invoke the supplied
function test
multiple times on the same element.
Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);