Chromium Code Reviews| Index: sdk/lib/core/iterable.dart |
| diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart |
| index cf05cdec4a55bdef6ece8554b8dfa90b4ebe6822..b48b609db607f5dab5c772b809756ace0c019e98 100644 |
| --- a/sdk/lib/core/iterable.dart |
| +++ b/sdk/lib/core/iterable.dart |
| @@ -14,7 +14,7 @@ part of dart.core; |
| * the iterator has now moved to the next element, |
| * which is then available as [Iterator.current]. |
| * If the call returns `false`, there are no more elements, |
| - * and `iterator.currrent` returns `null`. |
| + * and `iterator.current` returns `null`. |
| * |
| * You can create more than one iterator from the same `Iterable`. |
| * Each time `iterator` is read, it returns a new iterator, |
| @@ -83,15 +83,16 @@ abstract class Iterable<E> { |
| const Iterable(); |
| /** |
| - * Creates an `Iterable` that generates its elements dynamically. |
| + * Creates an `Iterable` which generates its elements dynamically. |
| * |
| - * An `Iterator` created by [iterator] will count from |
| - * zero to [:count - 1:], and call [generator] |
| - * with each index in turn to create the next value. |
| + * The generated iterable has [count] elements, |
| + * and the element at index `n` is computed by calling `generator(n)`. |
| + * Values are not cached, so each iteration computes the values again. |
| * |
| * If [generator] is omitted, it defaults to an identity function |
| - * on integers `(int x) => x`, so it should only be omitted if the type |
| - * parameter allows integer values. |
| + * on integers `(int x) => x`, so it may only be omitted if the type |
| + * parameter allows integer values. That is, if [E] is one of |
| + * `int`, `num`, `Object` or `dynamic`. |
| * |
| * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to |
| * `const [0, ..., n - 1].map(generator)`. |
| @@ -163,14 +164,14 @@ abstract class Iterable<E> { |
| * The matching elements have the same order in the returned iterable |
| * as they have in [iterator]. |
| * |
| - * 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 |
| + * 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] may invoke the supplied |
| * function [test] multiple times on the same element. |
| */ |
| - Iterable<E> where(bool test(E element)) => |
| - new WhereIterable<E>(this, test); |
| + Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test); |
| /** |
| * Expands each element of this [Iterable] into zero or more elements. |
| @@ -410,7 +411,7 @@ abstract class Iterable<E> { |
| } |
| /** |
| - * Returns an Iterable that provides all but the first [count] elements. |
| + * Returns an `Iterable` that provides all but the first [count] elements. |
| * |
| * When the returned iterable is iterated, it starts iterating over `this`, |
| * first skipping past the initial [count] elements. |
| @@ -419,6 +420,11 @@ abstract class Iterable<E> { |
| * After that, the remaining elements are iterated in the same order as |
| * in this iterable. |
| * |
| + * Some iterables may provide ways to skip initial elements without actively |
| + * iterating through them (for example when iterating a [List]). |
| + * Such iterables are allowed to completely ignore the inital skipped elements |
|
floitsch
2016/05/18 09:44:27
ignore the initial skipped elements.
(I would dro
Lasse Reichstein Nielsen
2016/05/18 09:54:15
Reworded entire paragraph, PTAL.
|
| + * and not, for example, compute their value. |
| + * |
| * The `count` must not be negative. |
| */ |
| Iterable<E> skip(int count) { |
| @@ -426,16 +432,16 @@ abstract class Iterable<E> { |
| } |
| /** |
| - * Returns an Iterable that skips leading elements while [test] is satisfied. |
| + * Returns an `Iterable` that skips leading elements while [test] is satisfied. |
| * |
| - * The filtering happens lazily. Every new Iterator of the returned |
| - * Iterable iterates over all elements of `this`. |
| + * The filtering happens lazily. Every new [Iterator] of the returned |
| + * iterable iterates over all elements of `this`. |
| * |
| * The returned iterable provides elements by iterating this iterable, |
| * but skipping over all initial elements where `test(element)` returns |
| * true. If all elements satisfy `test` the resulting iterable is empty, |
| * otherwise it iterates the remaining elements in their original order, |
| - * starting with the first element for which `test(element)` returns false. |
| + * starting with the first element for which `test(element)` returns `false`. |
| */ |
| Iterable<E> skipWhile(bool test(E value)) { |
| return new SkipWhileIterable<E>(this, test); |
| @@ -494,7 +500,7 @@ abstract class Iterable<E> { |
| /** |
| * Returns the first element that satisfies the given predicate [test]. |
| * |
| - * Iterates through elements and returns the first to satsify [test]. |
| + * Iterates through elements and returns the first to satisfy [test]. |
| * |
| * If no element satisfies [test], the result of invoking the [orElse] |
| * function is returned. |
| @@ -518,7 +524,7 @@ abstract class Iterable<E> { |
| * checks `test(element)` for each, |
| * and finally returns that last one that matched. |
| * |
| - * If no element satsfies [test], the result of invoking the [orElse] |
| + * If no element satisfies [test], the result of invoking the [orElse] |
| * function is returned. |
| * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| */ |
| @@ -603,72 +609,30 @@ abstract class Iterable<E> { |
| typedef E _Generator<E>(int index); |
| -class _GeneratorIterable<E> extends Iterable<E> |
| - implements EfficientLength { |
| - final int _start; |
| - final int _end; |
| +class _GeneratorIterable<E> extends ListIterable<E> { |
| + /// The length of the generated iterable. |
| + final int length; |
| + |
| + /// The function mapping indices to values. |
| final _Generator<E> _generator; |
| - /// Creates an iterable that builds the elements from a generator function. |
| + /// Creates the generated iterable. |
| /// |
| - /// The [generator] may be null, in which case the default generator |
| - /// enumerating the integer positions is used. This means that [int] must |
| - /// be assignable to [E] when no generator is provided. In practice this means |
| - /// that the generator can only be emitted when [E] is equal to `dynamic`, |
| - /// `int`, or `num`. The constructor will check that the types match. |
| - _GeneratorIterable(this._end, E generator(int n)) |
| - : _start = 0, |
| - // The `as` below is used as check to make sure that `int` is assignable |
| + /// If [generator] is `null`, it is checked that `int` is assignable to [E]. |
| + _GeneratorIterable(this.length, E generator(int index)) |
| + : // The `as` below is used as check to make sure that `int` is assignable |
| // to [E]. |
| _generator = (generator != null) ? generator : _id as _Generator<E>; |
| - _GeneratorIterable.slice(this._start, this._end, this._generator); |
| - |
| - Iterator<E> get iterator => |
| - new _GeneratorIterator<E>(_start, _end, _generator); |
| - int get length => _end - _start; |
| - |
| - Iterable<E> skip(int count) { |
| - RangeError.checkNotNegative(count, "count"); |
| - if (count == 0) return this; |
| - int newStart = _start + count; |
| - if (newStart >= _end) return new EmptyIterable<E>(); |
| - return new _GeneratorIterable<E>.slice(newStart, _end, _generator); |
| - } |
| - |
| - Iterable<E> take(int count) { |
| - RangeError.checkNotNegative(count, "count"); |
| - if (count == 0) return new EmptyIterable<E>(); |
| - int newEnd = _start + count; |
| - if (newEnd >= _end) return this; |
| - return new _GeneratorIterable<E>.slice(_start, newEnd, _generator); |
| + E elementAt(int index) { |
| + RangeError.checkValidIndex(index, this); |
| + return _generator(index); |
| } |
| + /// Helper function used as default _generator function. |
| static int _id(int n) => n; |
| } |
| -class _GeneratorIterator<E> implements Iterator<E> { |
| - final int _end; |
| - final _Generator<E> _generator; |
| - int _index; |
| - E _current; |
| - |
| - _GeneratorIterator(this._index, this._end, this._generator); |
| - |
| - bool moveNext() { |
| - if (_index < _end) { |
| - _current = _generator(_index); |
| - _index++; |
| - return true; |
| - } else { |
| - _current = null; |
| - return false; |
| - } |
| - } |
| - |
| - E get current => _current; |
| -} |
| - |
| /** |
| * An Iterator that allows moving backwards as well as forwards. |
| */ |