| // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of dart.core; |
| |
| /** |
| * A collection of values, or "elements", that can be accessed sequentially. |
| * |
| * The elements of the iterable are accessed by getting an [Iterator] |
| * using the [iterator] getter, and using it to step through the values. |
| * Stepping with the iterator is done by calling [Iterator.moveNext], |
| * and if the call returns `true`, |
| * 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. |
| * The [Iterator.current] value must only be used when the most |
| * recent call to [Iterator.moveNext] has returned `true`. |
| * If it is used before calling [Iterator.moveNext] the first time |
| * on an iterator, or after a call has returned false or has thrown an error, |
| * reading [Iterator.current] may throw or may return an arbitrary value. |
| * |
| * You can create more than one iterator from the same `Iterable`. |
| * Each time `iterator` is read, it returns a new iterator, |
| * and different iterators can be stepped through independently, |
| * each giving access to all the elements of the iterable. |
| * The iterators of the same iterable *should* provide the same values |
| * in the same order (unless the underlying collection is modified between |
| * the iterations, which some collections allow). |
| * |
| * You can also iterate over the elements of an `Iterable` |
| * using the for-in loop construct, which uses the `iterator` getter behind the |
| * scenes. |
| * For example, you can iterate over all of the keys of a [Map], |
| * because `Map` keys are iterable. |
| * |
| * Map kidsBooks = {'Matilda': 'Roald Dahl', |
| * 'Green Eggs and Ham': 'Dr Seuss', |
| * 'Where the Wild Things Are': 'Maurice Sendak'}; |
| * for (var book in kidsBooks.keys) { |
| * print('$book was written by ${kidsBooks[book]}'); |
| * } |
| * |
| * The [List] and [Set] classes are both `Iterable`, |
| * as are most classes in the `dart:collection` library. |
| * |
| * Some [Iterable] collections can be modified. |
| * Adding an element to a `List` or `Set` will change which elements it |
| * contains, and adding a new key to a `Map` changes the elements of [Map.keys]. |
| * Iterators created after the change will provide the new elements, and may |
| * or may not preserve the order of existing elements |
| * (for example, a [HashSet] may completely change its order when a single |
| * element is added). |
| * |
| * Changing a collection *while* it is being iterated |
| * is generally *not* allowed. |
| * Doing so will break the iteration, which is typically signalled |
| * by throwing a [ConcurrentModificationError] |
| * the next time [Iterator.moveNext] is called. |
| * The current value of [Iterator.current] getter |
| * should not be affected by the change in the collection, |
| * the `current` value was set by the previous call to [Iterator.moveNext]. |
| * |
| * Some iterables compute their elements dynamically every time they are |
| * iterated, like the one returned by [Iterable.generate] or the iterable |
| * returned by a `sync*` generator function. If the computation doesn't depend |
| * on other objects that may change, then the generated sequence should be |
| * the same one every time it's iterated. |
| * |
| * The members of `Iterable`, other than `iterator` itself, |
| * work by looking at the elements of the iterable. |
| * This can be implemented by running through the [iterator], but some classes |
| * may have more efficient ways of finding the result |
| * (like [last] or [length] on a [List], or [contains] on a [Set]). |
| * |
| * The methods that return another `Iterable` (like [map] and [where]) |
| * are all *lazy* - they will iterate the original (as necessary) |
| * every time the returned iterable is iterated, and not before. |
| * |
| * Since an iterable may be iterated more than once, it's not recommended to |
| * have detectable side-effects in the iterator. |
| * For methods like [map] and [where], the returned iterable will execute the |
| * argument function on every iteration, so those functions should also not |
| * have side effects. |
| */ |
| abstract class Iterable<E> { |
| // TODO(lrn): When we allow forwarding const constructors through |
| // mixin applications, make this class implement [IterableMixin]. |
| const Iterable(); |
| |
| /** |
| * Creates an `Iterable` which generates its elements dynamically. |
| * |
| * 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 may only be omitted if the type |
| * parameter allows integer values. That is, if [E] is a super-type |
| * of [int]. |
| * |
| * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to |
| * `const [0, ..., n - 1].map(generator)`. |
| */ |
| factory Iterable.generate(int count, [E generator(int index)?]) { |
| if (count <= 0) return EmptyIterable<E>(); |
| return _GeneratorIterable<E>(count, generator); |
| } |
| |
| /** |
| * Creates an empty iterable. |
| * |
| * The empty iterable has no elements, and iterating it always stops |
| * immediately. |
| */ |
| const factory Iterable.empty() = EmptyIterable<E>; |
| |
| /** |
| * Adapts [source] to be an `Iterable<T>`. |
| * |
| * Any time the iterable would produce an element that is not a [T], |
| * the element access will throw. If all elements of [source] are actually |
| * instances of [T], or if only elements that are actually instances of [T] |
| * are accessed, then the resulting iterable can be used as an `Iterable<T>`. |
| */ |
| static Iterable<T> castFrom<S, T>(Iterable<S> source) => |
| CastIterable<S, T>(source); |
| |
| /** |
| * Returns a new `Iterator` that allows iterating the elements of this |
| * `Iterable`. |
| * |
| * Iterable classes may specify the iteration order of their elements |
| * (for example [List] always iterate in index order), |
| * or they may leave it unspecified (for example a hash-based [Set] |
| * may iterate in any order). |
| * |
| * Each time `iterator` is read, it returns a new iterator, |
| * which can be used to iterate through all the elements again. |
| * The iterators of the same iterable can be stepped through independently, |
| * but should return the same elements in the same order, |
| * as long as the underlying collection isn't changed. |
| * |
| * Modifying the collection may cause new iterators to produce |
| * different elements, and may change the order of existing elements. |
| * A [List] specifies its iteration order precisely, |
| * so modifying the list changes the iteration order predictably. |
| * A hash-based [Set] may change its iteration order completely |
| * when adding a new element to the set. |
| * |
| * Modifying the underlying collection after creating the new iterator |
| * may cause an error the next time [Iterator.moveNext] is called |
| * on that iterator. |
| * Any *modifiable* iterable class should specify which operations will |
| * break iteration. |
| */ |
| Iterator<E> get iterator; |
| |
| /** |
| * Provides a view of this iterable as an iterable of [R] instances. |
| * |
| * If this iterable only contains instances of [R], all operations |
| * will work correctly. If any operation tries to access an element |
| * that is not an instance of [R], the access will throw instead. |
| * |
| * When the returned iterable creates a new object that depends on |
| * the type [R], e.g., from [toList], it will have exactly the type [R]. |
| */ |
| Iterable<R> cast<R>() => Iterable.castFrom<E, R>(this); |
| |
| /** |
| * Returns the lazy concatentation of this iterable and [other]. |
| * |
| * The returned iterable will provide the same elements as this iterable, |
| * and, after that, the elements of [other], in the same order as in the |
| * original iterables. |
| */ |
| Iterable<E> followedBy(Iterable<E> other) { |
| var self = this; // TODO(lrn): Remove when we can promote `this`. |
| if (self is EfficientLengthIterable<E>) { |
| return FollowedByIterable<E>.firstEfficient(self, other); |
| } |
| return FollowedByIterable<E>(this, other); |
| } |
| |
| /** |
| * Returns a new lazy [Iterable] with elements that are created by |
| * calling `f` on each element of this `Iterable` in iteration order. |
| * |
| * This method returns a view of the mapped elements. As long as the |
| * returned [Iterable] is not iterated over, the supplied function [f] will |
| * not be invoked. The transformed elements will not be cached. Iterating |
| * multiple times over the returned [Iterable] will invoke the supplied |
| * function [f] multiple times on the same element. |
| * |
| * Methods on the returned iterable are allowed to omit calling `f` |
| * on any element where the result isn't needed. |
| * For example, [elementAt] may call `f` only once. |
| */ |
| Iterable<T> map<T>(T f(E e)) => MappedIterable<E, T>(this, f); |
| |
| /** |
| * Returns a new lazy [Iterable] with all elements that satisfy the |
| * predicate [test]. |
| * |
| * 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] may invoke the supplied |
| * function [test] multiple times on the same element. |
| */ |
| Iterable<E> where(bool test(E element)) => WhereIterable<E>(this, test); |
| |
| /** |
| * Returns a new lazy [Iterable] with all elements that have type [T]. |
| * |
| * 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. |
| * Iterating will not cache results, and thus iterating multiple times over |
| * the returned [Iterable] may yield different results, |
| * if the underlying elements change between iterations. |
| */ |
| Iterable<T> whereType<T>() => WhereTypeIterable<T>(this); |
| |
| /** |
| * 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 iteration order. |
| * |
| * The returned [Iterable] is lazy, and calls [f] for each element |
| * of this every time it's iterated. |
| * |
| * Example: |
| * |
| * var pairs = [[1, 2], [3, 4]]; |
| * var flattened = pairs.expand((pair) => pair).toList(); |
| * print(flattened); // => [1, 2, 3, 4]; |
| * |
| * var input = [1, 2, 3]; |
| * var duplicated = input.expand((i) => [i, i]).toList(); |
| * print(duplicated); // => [1, 1, 2, 2, 3, 3] |
| * |
| */ |
| Iterable<T> expand<T>(Iterable<T> f(E element)) => |
| ExpandIterable<E, T>(this, f); |
| |
| /** |
| * Returns true if the collection contains an element equal to [element]. |
| * |
| * This operation will check each element in order for being equal to |
| * [element], unless it has a more efficient way to find an element |
| * equal to [element]. |
| * |
| * The equality used to determine whether [element] is equal to an element of |
| * the iterable defaults to the [Object.==] of the element. |
| * |
| * Some types of iterable may have a different equality used for its elements. |
| * For example, a [Set] may have a custom equality |
| * (see [Set.identity]) that its `contains` uses. |
| * Likewise the `Iterable` returned by a [Map.keys] call |
| * should use the same equality that the `Map` uses for keys. |
| */ |
| bool contains(Object? element) { |
| for (E e in this) { |
| if (e == element) return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Applies the function [f] to each element of this collection in iteration |
| * order. |
| */ |
| void forEach(void f(E element)) { |
| for (E element in this) f(element); |
| } |
| |
| /** |
| * Reduces a collection to a single value by iteratively combining elements |
| * of the collection using the provided function. |
| * |
| * The iterable must have at least one element. |
| * If it has only one element, that element is returned. |
| * |
| * Otherwise this method starts with the first element from the iterator, |
| * and then combines it with the remaining elements in iteration order, |
| * as if by: |
| * |
| * E value = iterable.first; |
| * iterable.skip(1).forEach((element) { |
| * value = combine(value, element); |
| * }); |
| * return value; |
| * |
| * 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 IterableElementError.noElement(); |
| } |
| E value = iterator.current; |
| while (iterator.moveNext()) { |
| value = combine(value, iterator.current); |
| } |
| return value; |
| } |
| |
| /** |
| * Reduces a collection to a single value by iteratively combining each |
| * element of the collection with an existing value |
| * |
| * Uses [initialValue] as the initial value, |
| * then iterates through the elements and updates the value with |
| * each element using the [combine] function, as if by: |
| * |
| * var value = initialValue; |
| * for (E element in this) { |
| * value = combine(value, element); |
| * } |
| * return value; |
| * |
| * Example of calculating the sum of an iterable: |
| * |
| * iterable.fold(0, (prev, element) => prev + element); |
| * |
| */ |
| T fold<T>(T initialValue, T combine(T previousValue, E element)) { |
| var value = initialValue; |
| for (E element in this) value = combine(value, element); |
| return value; |
| } |
| |
| /** |
| * Checks whether every element of this iterable satisfies [test]. |
| * |
| * Checks every element in iteration order, and returns `false` if |
| * any of them make [test] return `false`, otherwise returns `true`. |
| */ |
| bool every(bool test(E element)) { |
| for (E element in this) { |
| if (!test(element)) return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Converts each element to a [String] and concatenates the strings. |
| * |
| * Iterates through elements of this iterable, |
| * converts each one to a [String] by calling [Object.toString], |
| * and then concatenates the strings, with the |
| * [separator] string interleaved between the elements. |
| */ |
| String join([String separator = ""]) { |
| Iterator<E> iterator = this.iterator; |
| if (!iterator.moveNext()) return ""; |
| StringBuffer buffer = StringBuffer(); |
| if (separator == null || separator == "") { |
| do { |
| buffer.write(iterator.current.toString()); |
| } while (iterator.moveNext()); |
| } else { |
| buffer.write(iterator.current.toString()); |
| while (iterator.moveNext()) { |
| buffer.write(separator); |
| buffer.write(iterator.current.toString()); |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| /** |
| * Checks whether any element of this iterable satisfies [test]. |
| * |
| * Checks every element in iteration order, and returns `true` if |
| * any of them make [test] return `true`, otherwise returns false. |
| */ |
| bool any(bool test(E element)) { |
| for (E element in this) { |
| if (test(element)) return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Creates a [List] containing the elements of this [Iterable]. |
| * |
| * The elements are in iteration order. |
| * The list is fixed-length if [growable] is false. |
| */ |
| List<E> toList({bool growable = true}) { |
| return List<E>.of(this, growable: growable); |
| } |
| |
| /** |
| * Creates a [Set] containing the same elements as this iterable. |
| * |
| * The set may contain fewer elements than the iterable, |
| * if the iterable contains an element more than once, |
| * or it contains one or more elements that are equal. |
| * The order of the elements in the set is not guaranteed to be the same |
| * as for the iterable. |
| */ |
| Set<E> toSet() => Set<E>.of(this); |
| |
| /** |
| * Returns the number of elements in [this]. |
| * |
| * Counting all elements may involve iterating through all elements and can |
| * therefore be slow. |
| * Some iterables have a more efficient way to find the number of elements. |
| */ |
| int get length { |
| assert(this is! EfficientLengthIterable); |
| int count = 0; |
| Iterator it = iterator; |
| while (it.moveNext()) { |
| count++; |
| } |
| return count; |
| } |
| |
| /** |
| * Returns `true` if there are no elements in this collection. |
| * |
| * May be computed by checking if `iterator.moveNext()` returns `false`. |
| */ |
| bool get isEmpty => !iterator.moveNext(); |
| |
| /** |
| * Returns true if there is at least one element in this collection. |
| * |
| * May be computed by checking if `iterator.moveNext()` returns `true`. |
| */ |
| bool get isNotEmpty => !isEmpty; |
| |
| /** |
| * Returns a lazy iterable of the [count] first elements of this iterable. |
| * |
| * The returned `Iterable` may contain fewer than `count` elements, if `this` |
| * contains fewer than `count` elements. |
| * |
| * The elements can be computed by stepping through [iterator] until [count] |
| * elements have been seen. |
| * |
| * The `count` must not be negative. |
| */ |
| Iterable<E> take(int count) { |
| return TakeIterable<E>(this, count); |
| } |
| |
| /** |
| * Returns a lazy iterable of the leading elements satisfying [test]. |
| * |
| * The filtering happens lazily. Every new iterator of the returned |
| * iterable starts iterating over the elements of `this`. |
| * |
| * The elements can be computed by stepping through [iterator] until an |
| * element is found where `test(element)` is false. At that point, |
| * the returned iterable stops (its `moveNext()` returns false). |
| */ |
| Iterable<E> takeWhile(bool test(E value)) { |
| return TakeWhileIterable<E>(this, test); |
| } |
| |
| /** |
| * 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. |
| * If `this` has fewer than `count` elements, then the resulting Iterable is |
| * empty. |
| * After that, the remaining elements are iterated in the same order as |
| * in this iterable. |
| * |
| * Some iterables may be able to find later elements without first iterating |
| * through earlier elements, for example when iterating a [List]. |
| * Such iterables are allowed to ignore the initial skipped elements. |
| * |
| * The [count] must not be negative. |
| */ |
| Iterable<E> skip(int count) { |
| return SkipIterable<E>(this, count); |
| } |
| |
| /** |
| * 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 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`. |
| */ |
| Iterable<E> skipWhile(bool test(E value)) { |
| return SkipWhileIterable<E>(this, test); |
| } |
| |
| /** |
| * Returns the first element. |
| * |
| * Throws a [StateError] if `this` is empty. |
| * Otherwise returns the first element in the iteration order, |
| * equivalent to `this.elementAt(0)`. |
| */ |
| E get first { |
| Iterator<E> it = iterator; |
| if (!it.moveNext()) { |
| throw IterableElementError.noElement(); |
| } |
| return it.current; |
| } |
| |
| /** |
| * Returns the last element. |
| * |
| * Throws a [StateError] if `this` is empty. |
| * Otherwise may iterate through the elements and returns the last one |
| * seen. |
| * Some iterables may have more efficient ways to find the last element |
| * (for example a list can directly access the last element, |
| * without iterating through the previous ones). |
| */ |
| E get last { |
| Iterator<E> it = iterator; |
| if (!it.moveNext()) { |
| throw IterableElementError.noElement(); |
| } |
| E result; |
| do { |
| result = it.current; |
| } while (it.moveNext()); |
| return result; |
| } |
| |
| /** |
| * Checks that this iterable has only one element, and returns that element. |
| * |
| * Throws a [StateError] if `this` is empty or has more than one element. |
| */ |
| E get single { |
| Iterator<E> it = iterator; |
| if (!it.moveNext()) throw IterableElementError.noElement(); |
| E result = it.current; |
| if (it.moveNext()) throw IterableElementError.tooMany(); |
| return result; |
| } |
| |
| /** |
| * Returns the first element that satisfies the given predicate [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. |
| * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| */ |
| E firstWhere(bool test(E element), {E orElse()?}) { |
| for (E element in this) { |
| if (test(element)) return element; |
| } |
| if (orElse != null) return orElse(); |
| throw IterableElementError.noElement(); |
| } |
| |
| /** |
| * Returns the last element that satisfies the given predicate [test]. |
| * |
| * An iterable that can access its elements directly may check its |
| * elements in any order (for example a list starts by checking the |
| * last element and then moves towards the start of the list). |
| * The default implementation iterates elements in iteration order, |
| * checks `test(element)` for each, |
| * and finally returns that last one that matched. |
| * |
| * If no element satisfies [test], the result of invoking the [orElse] |
| * function is returned. |
| * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| */ |
| E lastWhere(bool test(E element), {E orElse()?}) { |
| late E result; |
| 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 IterableElementError.noElement(); |
| } |
| |
| /** |
| * Returns the single element that satisfies [test]. |
| * |
| * Checks elements to see if `test(element)` returns true. |
| * If exactly one element satisfies [test], that element is returned. |
| * If more than one matching element is found, throws [StateError]. |
| * If no matching element is found, returns the result of [orElse]. |
| * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| */ |
| E singleWhere(bool test(E element), {E orElse()?}) { |
| late E result; |
| bool foundMatching = false; |
| for (E element in this) { |
| if (test(element)) { |
| if (foundMatching) { |
| throw IterableElementError.tooMany(); |
| } |
| result = element; |
| foundMatching = true; |
| } |
| } |
| if (foundMatching) return result; |
| if (orElse != null) return orElse(); |
| throw IterableElementError.noElement(); |
| } |
| |
| /** |
| * Returns the [index]th element. |
| * |
| * The [index] must be non-negative and less than [length]. |
| * Index zero represents the first element (so `iterable.elementAt(0)` is |
| * equivalent to `iterable.first`). |
| * |
| * May iterate through the elements in iteration order, ignoring the |
| * first [index] elements and then returning the next. |
| * Some iterables may have a more efficient way to find the element. |
| */ |
| E elementAt(int index) { |
| RangeError.checkNotNegative(index, "index"); |
| int elementIndex = 0; |
| for (E element in this) { |
| if (index == elementIndex) return element; |
| elementIndex++; |
| } |
| throw RangeError.index(index, this, "index", null, elementIndex); |
| } |
| |
| /** |
| * Returns a string representation of (some of) the elements of `this`. |
| * |
| * Elements are represented by their own `toString` results. |
| * |
| * The default representation always contains the first three elements. |
| * If there are less than a hundred elements in the iterable, it also |
| * contains the last two elements. |
| * |
| * If the resulting string isn't above 80 characters, more elements are |
| * included from the start of the iterable. |
| * |
| * The conversion may omit calling `toString` on some elements if they |
| * are known to not occur in the output, and it may stop iterating after |
| * a hundred elements. |
| */ |
| String toString() => IterableBase.iterableToShortString(this, '(', ')'); |
| } |
| |
| class _GeneratorIterable<E> extends ListIterable<E> { |
| /// The length of the generated iterable. |
| final int length; |
| |
| /// The function mapping indices to values. |
| final E Function(int) _generator; |
| |
| /// Creates the generated iterable. |
| /// |
| /// 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 ?? (_id as E Function(int)); |
| |
| E elementAt(int index) { |
| RangeError.checkValidIndex(index, this); |
| return _generator(index); |
| } |
| |
| /// Helper function used as default _generator function. |
| static int _id(int n) => n; |
| } |
| |
| /** |
| * An [Iterator] that allows moving backwards as well as forwards. |
| */ |
| abstract class BidirectionalIterator<E> implements Iterator<E> { |
| /** |
| * Move back to the previous element. |
| * |
| * Returns true and updates [current] if successful. Returns false |
| * and updates [current] to an implementation defined state if there is no |
| * previous element |
| */ |
| bool movePrevious(); |
| } |