| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.core; | 5 part of dart.core; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A collection of values, or "elements", that can be accessed sequentially. | 8 * A collection of values, or "elements", that can be accessed sequentially. |
| 9 * | 9 * |
| 10 * The elements of the iterable are accessed by getting an [Iterator] | 10 * The elements of the iterable are accessed by getting an [Iterator] |
| 11 * using the [iterator] getter, and using it to step through the values. | 11 * using the [iterator] getter, and using it to step through the values. |
| 12 * Stepping with the iterator is done by calling [Iterator.moveNext], | 12 * Stepping with the iterator is done by calling [Iterator.moveNext], |
| 13 * and if the call returns `true`, | 13 * and if the call returns `true`, |
| 14 * the iterator has now moved to the next element, | 14 * the iterator has now moved to the next element, |
| 15 * which is then available as [Iterator.current]. | 15 * which is then available as [Iterator.current]. |
| 16 * If the call returns `false`, there are no more elements, | 16 * If the call returns `false`, there are no more elements, |
| 17 * and `iterator.currrent` returns `null`. | 17 * and `iterator.current` returns `null`. |
| 18 * | 18 * |
| 19 * You can create more than one iterator from the same `Iterable`. | 19 * You can create more than one iterator from the same `Iterable`. |
| 20 * Each time `iterator` is read, it returns a new iterator, | 20 * Each time `iterator` is read, it returns a new iterator, |
| 21 * and different iterators can be stepped through independently, | 21 * and different iterators can be stepped through independently, |
| 22 * each giving access to all the elements of the iterable. | 22 * each giving access to all the elements of the iterable. |
| 23 * The iterators of the same iterable *should* provide the same values | 23 * The iterators of the same iterable *should* provide the same values |
| 24 * in the same order (unless the underlying collection is modified between | 24 * in the same order (unless the underlying collection is modified between |
| 25 * the iterations, which some collections allow). | 25 * the iterations, which some collections allow). |
| 26 * | 26 * |
| 27 * You can also iterate over the elements of an `Iterable` | 27 * You can also iterate over the elements of an `Iterable` |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 * Since an iterable may be iterated more than once, it's not recommended to | 76 * Since an iterable may be iterated more than once, it's not recommended to |
| 77 * have detectable side-effects in the iterator. | 77 * have detectable side-effects in the iterator. |
| 78 * For methods like [map] and [while], the returned iterable will execute the | 78 * For methods like [map] and [while], the returned iterable will execute the |
| 79 * argument function on every iteration, so those functions should also not | 79 * argument function on every iteration, so those functions should also not |
| 80 * have side effects. | 80 * have side effects. |
| 81 */ | 81 */ |
| 82 abstract class Iterable<E> { | 82 abstract class Iterable<E> { |
| 83 const Iterable(); | 83 const Iterable(); |
| 84 | 84 |
| 85 /** | 85 /** |
| 86 * Creates an `Iterable` that generates its elements dynamically. | 86 * Creates an `Iterable` which generates its elements dynamically. |
| 87 * | 87 * |
| 88 * An `Iterator` created by [iterator] will count from | 88 * The generated iterable has [count] elements, |
| 89 * zero to [:count - 1:], and call [generator] | 89 * and the element at index `n` is computed by calling `generator(n)`. |
| 90 * with each index in turn to create the next value. | 90 * Values are not cached, so each iteration computes the values again. |
| 91 * | 91 * |
| 92 * If [generator] is omitted, it defaults to an identity function | 92 * If [generator] is omitted, it defaults to an identity function |
| 93 * on integers `(int x) => x`, so it should only be omitted if the type | 93 * on integers `(int x) => x`, so it may only be omitted if the type |
| 94 * parameter allows integer values. | 94 * parameter allows integer values. That is, if [E] is one of |
| 95 * `int`, `num`, `Object` or `dynamic`. |
| 95 * | 96 * |
| 96 * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to | 97 * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to |
| 97 * `const [0, ..., n - 1].map(generator)`. | 98 * `const [0, ..., n - 1].map(generator)`. |
| 98 */ | 99 */ |
| 99 factory Iterable.generate(int count, [E generator(int index)]) { | 100 factory Iterable.generate(int count, [E generator(int index)]) { |
| 100 if (count <= 0) return new EmptyIterable<E>(); | 101 if (count <= 0) return new EmptyIterable<E>(); |
| 101 return new _GeneratorIterable<E>(count, generator); | 102 return new _GeneratorIterable<E>(count, generator); |
| 102 } | 103 } |
| 103 | 104 |
| 104 /** | 105 /** |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E e)) => | 157 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E e)) => |
| 157 new MappedIterable<E, dynamic/*=T*/>(this, f); | 158 new MappedIterable<E, dynamic/*=T*/>(this, f); |
| 158 | 159 |
| 159 /** | 160 /** |
| 160 * Returns a new lazy [Iterable] with all elements that satisfy the | 161 * Returns a new lazy [Iterable] with all elements that satisfy the |
| 161 * predicate [test]. | 162 * predicate [test]. |
| 162 * | 163 * |
| 163 * The matching elements have the same order in the returned iterable | 164 * The matching elements have the same order in the returned iterable |
| 164 * as they have in [iterator]. | 165 * as they have in [iterator]. |
| 165 * | 166 * |
| 166 * This method returns a view of the mapped elements. As long as the | 167 * This method returns a view of the mapped elements. |
| 167 * returned [Iterable] is not iterated over, the supplied function [test] will | 168 * As long as the returned [Iterable] is not iterated over, |
| 168 * not be invoked. Iterating will not cache results, and thus iterating | 169 * the supplied function [test] will not be invoked. |
| 169 * multiple times over the returned [Iterable] will invoke the supplied | 170 * Iterating will not cache results, and thus iterating multiple times over |
| 171 * the returned [Iterable] may invoke the supplied |
| 170 * function [test] multiple times on the same element. | 172 * function [test] multiple times on the same element. |
| 171 */ | 173 */ |
| 172 Iterable<E> where(bool test(E element)) => | 174 Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test); |
| 173 new WhereIterable<E>(this, test); | |
| 174 | 175 |
| 175 /** | 176 /** |
| 176 * Expands each element of this [Iterable] into zero or more elements. | 177 * Expands each element of this [Iterable] into zero or more elements. |
| 177 * | 178 * |
| 178 * The resulting Iterable runs through the elements returned | 179 * The resulting Iterable runs through the elements returned |
| 179 * by [f] for each element of this, in iteration order. | 180 * by [f] for each element of this, in iteration order. |
| 180 * | 181 * |
| 181 * The returned [Iterable] is lazy, and calls [f] for each element | 182 * The returned [Iterable] is lazy, and calls [f] for each element |
| 182 * of this every time it's iterated. | 183 * of this every time it's iterated. |
| 183 */ | 184 */ |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 * | 404 * |
| 404 * The elements can be computed by stepping through [iterator] until an | 405 * The elements can be computed by stepping through [iterator] until an |
| 405 * element is found where `test(element)` is false. At that point, | 406 * element is found where `test(element)` is false. At that point, |
| 406 * the returned iterable stops (its `moveNext()` returns false). | 407 * the returned iterable stops (its `moveNext()` returns false). |
| 407 */ | 408 */ |
| 408 Iterable<E> takeWhile(bool test(E value)) { | 409 Iterable<E> takeWhile(bool test(E value)) { |
| 409 return new TakeWhileIterable<E>(this, test); | 410 return new TakeWhileIterable<E>(this, test); |
| 410 } | 411 } |
| 411 | 412 |
| 412 /** | 413 /** |
| 413 * Returns an Iterable that provides all but the first [count] elements. | 414 * Returns an [Iterable] that provides all but the first [count] elements. |
| 414 * | 415 * |
| 415 * When the returned iterable is iterated, it starts iterating over `this`, | 416 * When the returned iterable is iterated, it starts iterating over `this`, |
| 416 * first skipping past the initial [count] elements. | 417 * first skipping past the initial [count] elements. |
| 417 * If `this` has fewer than `count` elements, then the resulting Iterable is | 418 * If `this` has fewer than `count` elements, then the resulting Iterable is |
| 418 * empty. | 419 * empty. |
| 419 * After that, the remaining elements are iterated in the same order as | 420 * After that, the remaining elements are iterated in the same order as |
| 420 * in this iterable. | 421 * in this iterable. |
| 421 * | 422 * |
| 422 * The `count` must not be negative. | 423 * Some iterables may be able to find later elements without first iterating |
| 424 * through earlier elements, for example when iterating a [List]. |
| 425 * Such iterables are allowed to ignore the initial skipped elements. |
| 426 * |
| 427 * The [count] must not be negative. |
| 423 */ | 428 */ |
| 424 Iterable<E> skip(int count) { | 429 Iterable<E> skip(int count) { |
| 425 return new SkipIterable<E>(this, count); | 430 return new SkipIterable<E>(this, count); |
| 426 } | 431 } |
| 427 | 432 |
| 428 /** | 433 /** |
| 429 * Returns an Iterable that skips leading elements while [test] is satisfied. | 434 * Returns an `Iterable` that skips leading elements while [test] is satisfied
. |
| 430 * | 435 * |
| 431 * The filtering happens lazily. Every new Iterator of the returned | 436 * The filtering happens lazily. Every new [Iterator] of the returned |
| 432 * Iterable iterates over all elements of `this`. | 437 * iterable iterates over all elements of `this`. |
| 433 * | 438 * |
| 434 * The returned iterable provides elements by iterating this iterable, | 439 * The returned iterable provides elements by iterating this iterable, |
| 435 * but skipping over all initial elements where `test(element)` returns | 440 * but skipping over all initial elements where `test(element)` returns |
| 436 * true. If all elements satisfy `test` the resulting iterable is empty, | 441 * true. If all elements satisfy `test` the resulting iterable is empty, |
| 437 * otherwise it iterates the remaining elements in their original order, | 442 * otherwise it iterates the remaining elements in their original order, |
| 438 * starting with the first element for which `test(element)` returns false. | 443 * starting with the first element for which `test(element)` returns `false`. |
| 439 */ | 444 */ |
| 440 Iterable<E> skipWhile(bool test(E value)) { | 445 Iterable<E> skipWhile(bool test(E value)) { |
| 441 return new SkipWhileIterable<E>(this, test); | 446 return new SkipWhileIterable<E>(this, test); |
| 442 } | 447 } |
| 443 | 448 |
| 444 /** | 449 /** |
| 445 * Returns the first element. | 450 * Returns the first element. |
| 446 * | 451 * |
| 447 * Throws a [StateError] if `this` is empty. | 452 * Throws a [StateError] if `this` is empty. |
| 448 * Otherwise returns the first element in the iteration order, | 453 * Otherwise returns the first element in the iteration order, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 Iterator<E> it = iterator; | 492 Iterator<E> it = iterator; |
| 488 if (!it.moveNext()) throw IterableElementError.noElement(); | 493 if (!it.moveNext()) throw IterableElementError.noElement(); |
| 489 E result = it.current; | 494 E result = it.current; |
| 490 if (it.moveNext()) throw IterableElementError.tooMany(); | 495 if (it.moveNext()) throw IterableElementError.tooMany(); |
| 491 return result; | 496 return result; |
| 492 } | 497 } |
| 493 | 498 |
| 494 /** | 499 /** |
| 495 * Returns the first element that satisfies the given predicate [test]. | 500 * Returns the first element that satisfies the given predicate [test]. |
| 496 * | 501 * |
| 497 * Iterates through elements and returns the first to satsify [test]. | 502 * Iterates through elements and returns the first to satisfy [test]. |
| 498 * | 503 * |
| 499 * If no element satisfies [test], the result of invoking the [orElse] | 504 * If no element satisfies [test], the result of invoking the [orElse] |
| 500 * function is returned. | 505 * function is returned. |
| 501 * If [orElse] is omitted, it defaults to throwing a [StateError]. | 506 * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| 502 */ | 507 */ |
| 503 E firstWhere(bool test(E element), { E orElse() }) { | 508 E firstWhere(bool test(E element), { E orElse() }) { |
| 504 for (E element in this) { | 509 for (E element in this) { |
| 505 if (test(element)) return element; | 510 if (test(element)) return element; |
| 506 } | 511 } |
| 507 if (orElse != null) return orElse(); | 512 if (orElse != null) return orElse(); |
| 508 throw IterableElementError.noElement(); | 513 throw IterableElementError.noElement(); |
| 509 } | 514 } |
| 510 | 515 |
| 511 /** | 516 /** |
| 512 * Returns the last element that satisfies the given predicate [test]. | 517 * Returns the last element that satisfies the given predicate [test]. |
| 513 * | 518 * |
| 514 * An iterable that can access its elements directly may check its | 519 * An iterable that can access its elements directly may check its |
| 515 * elements in any order (for example a list starts by checking the | 520 * elements in any order (for example a list starts by checking the |
| 516 * last element and then moves towards the start of the list). | 521 * last element and then moves towards the start of the list). |
| 517 * The default implementation iterates elements in iteration order, | 522 * The default implementation iterates elements in iteration order, |
| 518 * checks `test(element)` for each, | 523 * checks `test(element)` for each, |
| 519 * and finally returns that last one that matched. | 524 * and finally returns that last one that matched. |
| 520 * | 525 * |
| 521 * If no element satsfies [test], the result of invoking the [orElse] | 526 * If no element satisfies [test], the result of invoking the [orElse] |
| 522 * function is returned. | 527 * function is returned. |
| 523 * If [orElse] is omitted, it defaults to throwing a [StateError]. | 528 * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| 524 */ | 529 */ |
| 525 E lastWhere(bool test(E element), {E orElse()}) { | 530 E lastWhere(bool test(E element), {E orElse()}) { |
| 526 E result = null; | 531 E result = null; |
| 527 bool foundMatching = false; | 532 bool foundMatching = false; |
| 528 for (E element in this) { | 533 for (E element in this) { |
| 529 if (test(element)) { | 534 if (test(element)) { |
| 530 result = element; | 535 result = element; |
| 531 foundMatching = true; | 536 foundMatching = true; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 * | 601 * |
| 597 * The conversion may omit calling `toString` on some elements if they | 602 * The conversion may omit calling `toString` on some elements if they |
| 598 * are known to not occur in the output, and it may stop iterating after | 603 * are known to not occur in the output, and it may stop iterating after |
| 599 * a hundred elements. | 604 * a hundred elements. |
| 600 */ | 605 */ |
| 601 String toString() => IterableBase.iterableToShortString(this, '(', ')'); | 606 String toString() => IterableBase.iterableToShortString(this, '(', ')'); |
| 602 } | 607 } |
| 603 | 608 |
| 604 typedef E _Generator<E>(int index); | 609 typedef E _Generator<E>(int index); |
| 605 | 610 |
| 606 class _GeneratorIterable<E> extends Iterable<E> | 611 class _GeneratorIterable<E> extends ListIterable<E> { |
| 607 implements EfficientLength { | 612 /// The length of the generated iterable. |
| 608 final int _start; | 613 final int length; |
| 609 final int _end; | 614 |
| 615 /// The function mapping indices to values. |
| 610 final _Generator<E> _generator; | 616 final _Generator<E> _generator; |
| 611 | 617 |
| 612 /// Creates an iterable that builds the elements from a generator function. | 618 /// Creates the generated iterable. |
| 613 /// | 619 /// |
| 614 /// The [generator] may be null, in which case the default generator | 620 /// If [generator] is `null`, it is checked that `int` is assignable to [E]. |
| 615 /// enumerating the integer positions is used. This means that [int] must | 621 _GeneratorIterable(this.length, E generator(int index)) |
| 616 /// be assignable to [E] when no generator is provided. In practice this means | 622 : // The `as` below is used as check to make sure that `int` is assignable |
| 617 /// that the generator can only be emitted when [E] is equal to `dynamic`, | |
| 618 /// `int`, or `num`. The constructor will check that the types match. | |
| 619 _GeneratorIterable(this._end, E generator(int n)) | |
| 620 : _start = 0, | |
| 621 // The `as` below is used as check to make sure that `int` is assignable | |
| 622 // to [E]. | 623 // to [E]. |
| 623 _generator = (generator != null) ? generator : _id as _Generator<E>; | 624 _generator = (generator != null) ? generator : _id as _Generator<E>; |
| 624 | 625 |
| 625 _GeneratorIterable.slice(this._start, this._end, this._generator); | 626 E elementAt(int index) { |
| 626 | 627 RangeError.checkValidIndex(index, this); |
| 627 Iterator<E> get iterator => | 628 return _generator(index); |
| 628 new _GeneratorIterator<E>(_start, _end, _generator); | |
| 629 int get length => _end - _start; | |
| 630 | |
| 631 Iterable<E> skip(int count) { | |
| 632 RangeError.checkNotNegative(count, "count"); | |
| 633 if (count == 0) return this; | |
| 634 int newStart = _start + count; | |
| 635 if (newStart >= _end) return new EmptyIterable<E>(); | |
| 636 return new _GeneratorIterable<E>.slice(newStart, _end, _generator); | |
| 637 } | 629 } |
| 638 | 630 |
| 639 Iterable<E> take(int count) { | 631 /// Helper function used as default _generator function. |
| 640 RangeError.checkNotNegative(count, "count"); | |
| 641 if (count == 0) return new EmptyIterable<E>(); | |
| 642 int newEnd = _start + count; | |
| 643 if (newEnd >= _end) return this; | |
| 644 return new _GeneratorIterable<E>.slice(_start, newEnd, _generator); | |
| 645 } | |
| 646 | |
| 647 static int _id(int n) => n; | 632 static int _id(int n) => n; |
| 648 } | 633 } |
| 649 | 634 |
| 650 class _GeneratorIterator<E> implements Iterator<E> { | |
| 651 final int _end; | |
| 652 final _Generator<E> _generator; | |
| 653 int _index; | |
| 654 E _current; | |
| 655 | |
| 656 _GeneratorIterator(this._index, this._end, this._generator); | |
| 657 | |
| 658 bool moveNext() { | |
| 659 if (_index < _end) { | |
| 660 _current = _generator(_index); | |
| 661 _index++; | |
| 662 return true; | |
| 663 } else { | |
| 664 _current = null; | |
| 665 return false; | |
| 666 } | |
| 667 } | |
| 668 | |
| 669 E get current => _current; | |
| 670 } | |
| 671 | |
| 672 /** | 635 /** |
| 673 * An Iterator that allows moving backwards as well as forwards. | 636 * An Iterator that allows moving backwards as well as forwards. |
| 674 */ | 637 */ |
| 675 abstract class BidirectionalIterator<E> implements Iterator<E> { | 638 abstract class BidirectionalIterator<E> implements Iterator<E> { |
| 676 /** | 639 /** |
| 677 * Move back to the previous element. | 640 * Move back to the previous element. |
| 678 * | 641 * |
| 679 * Returns true and updates [current] if successful. Returns false | 642 * Returns true and updates [current] if successful. Returns false |
| 680 * and sets [current] to null if there is no previous element. | 643 * and sets [current] to null if there is no previous element. |
| 681 */ | 644 */ |
| 682 bool movePrevious(); | 645 bool movePrevious(); |
| 683 } | 646 } |
| OLD | NEW |