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 |