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 * An object that uses an [Iterator] to serve objects one at a time. | 8 * A collection of values, or "elements", that can be accessed sequentially. |
9 * | 9 * |
10 * You can iterate over all objects served by an Iterable object | 10 * The elements of the iterable are accessed by getting an [Iterator] |
11 * using the for-in loop construct. | 11 * using the [iterator] getter, and using it to step through the values. |
12 * For example, you can iterate over all of the keys in a [Map], | 12 * Stepping with the iterator is done by calling [Iterator.moveNext], |
13 * because Map keys are iterable. | 13 * and if the call returns `true`, |
| 14 * the iterator has now moved to the next element, |
| 15 * which is then available as [Iterator.current]. |
| 16 * If the call returns `false`, there are no more elements, |
| 17 * and `iterator.currrent` returns `null`. |
| 18 * |
| 19 * You can create more than one iterator from the same `Iterable`. |
| 20 * Each time `iterator` is read, it returns a new iterator, |
| 21 * and different iterators can be stepped through independently, |
| 22 * each giving access to all the elements of the iterable. |
| 23 * The iterators of the same iterable *should* provide the same values |
| 24 * in the same order (unless the underlying collection is modified between |
| 25 * the iterations, which some collections allow). |
| 26 * |
| 27 * You can also iterate over the elements of an `Iterable` |
| 28 * using the for-in loop construct, which uses the `iterator` getter behind the |
| 29 * scenes. |
| 30 * For example, you can iterate over all of the keys of a [Map], |
| 31 * because `Map` keys are iterable. |
14 * | 32 * |
15 * Map kidsBooks = {'Matilda': 'Roald Dahl', | 33 * Map kidsBooks = {'Matilda': 'Roald Dahl', |
16 * 'Green Eggs and Ham': 'Dr Seuss', | 34 * 'Green Eggs and Ham': 'Dr Seuss', |
17 * 'Where the Wild Things Are': 'Maurice Sendak'}; | 35 * 'Where the Wild Things Are': 'Maurice Sendak'}; |
18 * for (var book in kidsBooks.keys) { | 36 * for (var book in kidsBooks.keys) { |
19 * print('$book was written by ${kidsBooks[book]}'); | 37 * print('$book was written by ${kidsBooks[book]}'); |
20 * } | 38 * } |
21 * | 39 * |
22 * The [List] class and the [Set] class implement this interface, | 40 * The [List] and [Set] classes are both `Iterable`, |
23 * as do classes in the [dart:collection](#dart-collection) library. | 41 * as are most classes in the [dart:collection](#dart-collection) library. |
24 * | 42 * |
25 * You can implement Iterable in your own class. | 43 * Some [Iterable] collections can be modified. |
26 * If you do, then an instance of your Iterable class | 44 * Adding an element to a `List` or `Set` will change which elements it |
27 * can be the right-hand side of a for-in construct. | 45 * contains, and adding a new key to a `Map` changes the elements of [Map.keys]. |
| 46 * Iterators created after the change will provide the new elements, and may |
| 47 * or may not preserve the order of existing elements |
| 48 * (for example, a [HashSet] may completely change its order when a single |
| 49 * element is added). |
28 * | 50 * |
29 * Some subclasss of [Iterable] can be modified. It is generally not allowed | 51 * Changing a collection *while* it is being iterated |
30 * to modify such collections while they are being iterated. Doing so will break | 52 * is generally *not* allowed. |
31 * the iteration, which is typically signalled by throwing a | 53 * Doing so will break the iteration, which is typically signalled |
32 * [ConcurrentModificationError] when it is detected. | 54 * by throwing a [ConcurrentModificationError] |
| 55 * the next time [Iterator.moveNext] is called. |
| 56 * The current value of [Iterator.current] getter |
| 57 * should not be affected by the change in the collection, |
| 58 * the `current` value was set by the previous call to [Iterator.moveNext]. |
| 59 * |
| 60 * Some iterables compute their elements dynamically every time they are |
| 61 * iterated, like the one returned by [Iterable.generate] or the iterable |
| 62 * returned by a `sync*` generator function. If the computation doesn't depend |
| 63 * on other objects that may change, then the generated sequence should be |
| 64 * the same one every time it's iterated. |
| 65 * |
| 66 * The members of `Iterable`, other than `iterator` itself, |
| 67 * work by looking at the elements of the iterable. |
| 68 * This can be implemented by running through the [iterator], but some classes |
| 69 * may have more efficient ways of finding the result |
| 70 * (like [last] or [length] on a [List], or [contains] on a [Set]). |
| 71 * |
| 72 * The methods that return another `Iterable` (like [map] and [where]) |
| 73 * are all *lazy* - they will iterate the original (as necessary) |
| 74 * every time the returned iterable is iterated, and not before. |
| 75 * |
| 76 * Since an iterable may be iterated more than once, it's not recommended to |
| 77 * have detectable side-effects in the iterator. |
| 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 |
| 80 * have side effects. |
33 */ | 81 */ |
34 abstract class Iterable<E> { | 82 abstract class Iterable<E> { |
35 const Iterable(); | 83 const Iterable(); |
36 | 84 |
37 /** | 85 /** |
38 * Creates an Iterable that generates its elements dynamically. | 86 * Creates an `Iterable` that generates its elements dynamically. |
39 * | 87 * |
40 * The Iterators created by the Iterable count from | 88 * An `Iterator` created by [iterator] will count from |
41 * zero to [:count - 1:] while iterating, and call [generator] | 89 * zero to [:count - 1:], and call [generator] |
42 * with that index to create the next value. | 90 * with each index in turn to create the next value. |
43 * | 91 * |
44 * If [generator] is omitted, it defaults to an identity function | 92 * If [generator] is omitted, it defaults to an identity function |
45 * on integers `(int x) => x`, so it should only be omitted if the type | 93 * on integers `(int x) => x`, so it should only be omitted if the type |
46 * parameter allows integer values. | 94 * parameter allows integer values. |
47 * | 95 * |
48 * As an Iterable, [:new Iterable.generate(n, generator)):] is equivalent to | 96 * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to |
49 * [:const [0, ..., n - 1].map(generator):] | 97 * `const [0, ..., n - 1].map(generator)`. |
50 */ | 98 */ |
51 factory Iterable.generate(int count, [E generator(int index)]) { | 99 factory Iterable.generate(int count, [E generator(int index)]) { |
52 if (count <= 0) return new EmptyIterable<E>(); | 100 if (count <= 0) return new EmptyIterable<E>(); |
53 return new _GeneratorIterable<E>(count, generator); | 101 return new _GeneratorIterable<E>(count, generator); |
54 } | 102 } |
55 | 103 |
56 /** | 104 /** |
| 105 * Creates an empty iterable. |
| 106 * |
| 107 * The empty iterable has no elements, and iterating it always stops |
| 108 * immediately. |
| 109 */ |
| 110 const factory Iterable.empty() = EmptyIterable<E>; |
| 111 |
| 112 /** |
57 * Returns a new `Iterator` that allows iterating the elements of this | 113 * Returns a new `Iterator` that allows iterating the elements of this |
58 * `Iterable`. | 114 * `Iterable`. |
59 * | 115 * |
60 * Modifying the underlying data after creating the new iterator | 116 * Iterable classes may specify the iteration order of their elements |
61 * may cause an error the next time [Iterator.moveNext] is called. | 117 * (for example [List] always iterate in index order), |
| 118 * or they may leave it unspecified (for example a hash-based [Set] |
| 119 * may iterate in any order). |
| 120 * |
| 121 * Each time `iterator` is read, it returns a new iterator, |
| 122 * which can be used to iterate through all the elements again. |
| 123 * The iterators of the same iterable can be stepped through independently, |
| 124 * but should return the same elements in the same order, |
| 125 * as long as the underlying collection isn't changed. |
| 126 * |
| 127 * Modifying the collection may cause new iterators to produce |
| 128 * different elements, and may change the order of existing elements. |
| 129 * A [List] specifies its iteration order precisely, |
| 130 * so modifying the list changes the iteration order predictably. |
| 131 * A hash-based [Set] may change its iteration order completely |
| 132 * when adding a new element to the set. |
| 133 * |
| 134 * Modifying the underlying collection after creating the new iterator |
| 135 * may cause an error the next time [Iterator.moveNext] is called |
| 136 * on that iterator. |
| 137 * Any *modifiable* iterable class should specify which operations will |
| 138 * break iteration. |
62 */ | 139 */ |
63 Iterator<E> get iterator; | 140 Iterator<E> get iterator; |
64 | 141 |
65 /** | 142 /** |
66 * Returns a new lazy [Iterable] with elements that are created by | 143 * Returns a new lazy [Iterable] with elements that are created by |
67 * calling `f` on the elements of this `Iterable`. | 144 * calling `f` on each element of this `Iterable` in iteration order. |
68 * | 145 * |
69 * This method returns a view of the mapped elements. As long as the | 146 * This method returns a view of the mapped elements. As long as the |
70 * returned [Iterable] is not iterated over, the supplied function [f] will | 147 * returned [Iterable] is not iterated over, the supplied function [f] will |
71 * not be invoked. The transformed elements will not be cached. Iterating | 148 * not be invoked. The transformed elements will not be cached. Iterating |
72 * multiple times over the the returned [Iterable] will invoke the supplied | 149 * multiple times over the the returned [Iterable] will invoke the supplied |
73 * function [f] multiple times on the same element. | 150 * function [f] multiple times on the same element. |
| 151 * |
| 152 * Methods on the returned iterable are allowed to omit calling `f` |
| 153 * on any element where the result isn't needed. |
| 154 * For example, [elementAt] may call `f` only once. |
74 */ | 155 */ |
75 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)); | 156 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E e)) => |
| 157 new MappedIterable<E, dynamic/*=T*/>(this, f); |
76 | 158 |
77 /** | 159 /** |
78 * Returns a new lazy [Iterable] with all elements that satisfy the | 160 * Returns a new lazy [Iterable] with all elements that satisfy the |
79 * predicate [test]. | 161 * predicate [test]. |
80 * | 162 * |
| 163 * The matching elements have the same order in the returned iterable |
| 164 * as they have in [iterator]. |
| 165 * |
81 * This method returns a view of the mapped elements. As long as the | 166 * This method returns a view of the mapped elements. As long as the |
82 * returned [Iterable] is not iterated over, the supplied function [test] will | 167 * returned [Iterable] is not iterated over, the supplied function [test] will |
83 * not be invoked. Iterating will not cache results, and thus iterating | 168 * not be invoked. Iterating will not cache results, and thus iterating |
84 * multiple times over the returned [Iterable] will invoke the supplied | 169 * multiple times over the returned [Iterable] will invoke the supplied |
85 * function [test] multiple times on the same element. | 170 * function [test] multiple times on the same element. |
86 */ | 171 */ |
87 Iterable<E> where(bool test(E element)); | 172 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); |
88 | 173 |
89 /** | 174 /** |
90 * Expands each element of this [Iterable] into zero or more elements. | 175 * Expands each element of this [Iterable] into zero or more elements. |
91 * | 176 * |
92 * The resulting Iterable runs through the elements returned | 177 * The resulting Iterable runs through the elements returned |
93 * by [f] for each element of this, in order. | 178 * by [f] for each element of this, in iteration order. |
94 * | 179 * |
95 * The returned [Iterable] is lazy, and calls [f] for each element | 180 * The returned [Iterable] is lazy, and calls [f] for each element |
96 * of this every time it's iterated. | 181 * of this every time it's iterated. |
97 */ | 182 */ |
98 Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element)); | 183 Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element)) => |
| 184 new ExpandIterable<E, dynamic/*=T*/>(this, f); |
99 | 185 |
100 /** | 186 /** |
101 * Returns true if the collection contains an element equal to [element]. | 187 * Returns true if the collection contains an element equal to [element]. |
102 * | 188 * |
| 189 * This operation will check each element in order for being equal to |
| 190 * [element], unless it has a more efficient way to find an element |
| 191 * equal to [element]. |
| 192 * |
103 * The equality used to determine whether [element] is equal to an element of | 193 * The equality used to determine whether [element] is equal to an element of |
104 * the iterable, depends on the type of iterable. | 194 * the iterable defaults to the [Object.operator==] of the element. |
| 195 * |
| 196 * Some types of iterable may have a different equality used for its elements. |
105 * For example, a [Set] may have a custom equality | 197 * For example, a [Set] may have a custom equality |
106 * (see, e.g., [Set.identical]) that its `contains` uses. | 198 * (see [Set.identical]) that its `contains` uses. |
107 * Likewise the `Iterable` returned by a [Map.keys] call | 199 * Likewise the `Iterable` returned by a [Map.keys] call |
108 * will likely use the same equality that the `Map` uses for keys. | 200 * should use the same equality that the `Map` uses for keys. |
109 */ | 201 */ |
110 bool contains(Object element); | 202 bool contains(Object element) { |
| 203 for (E e in this) { |
| 204 if (e == element) return true; |
| 205 } |
| 206 return false; |
| 207 } |
| 208 |
111 | 209 |
112 /** | 210 /** |
113 * Applies the function [f] to each element of this collection. | 211 * Applies the function [f] to each element of this collection in iteration |
| 212 * order. |
114 */ | 213 */ |
115 void forEach(void f(E element)); | 214 void forEach(void f(E element)) { |
| 215 for (E element in this) f(element); |
| 216 } |
116 | 217 |
117 /** | 218 /** |
118 * Reduces a collection to a single value by iteratively combining elements | 219 * Reduces a collection to a single value by iteratively combining elements |
119 * of the collection using the provided function. | 220 * of the collection using the provided function. |
120 * | 221 * |
| 222 * The iterable must have at least one element. |
| 223 * If it has only one element, that element is returned. |
| 224 * |
| 225 * Otherwise this method starts with the first element from the iterator, |
| 226 * and then combines it with the remaining elements in iteration order, |
| 227 * as if by: |
| 228 * |
| 229 * E value = iterable.first; |
| 230 * iterable.skip(1).forEach((element) { |
| 231 * value = combine(value, element); |
| 232 * }); |
| 233 * return value; |
| 234 * |
121 * Example of calculating the sum of an iterable: | 235 * Example of calculating the sum of an iterable: |
122 * | 236 * |
123 * iterable.reduce((value, element) => value + element); | 237 * iterable.reduce((value, element) => value + element); |
124 * | 238 * |
125 */ | 239 */ |
126 E reduce(E combine(E value, E element)); | 240 E reduce(E combine(E value, E element)) { |
| 241 Iterator<E> iterator = this.iterator; |
| 242 if (!iterator.moveNext()) { |
| 243 throw IterableElementError.noElement(); |
| 244 } |
| 245 E value = iterator.current; |
| 246 while (iterator.moveNext()) { |
| 247 value = combine(value, iterator.current); |
| 248 } |
| 249 return value; |
| 250 } |
127 | 251 |
128 /** | 252 /** |
129 * Reduces a collection to a single value by iteratively combining each | 253 * Reduces a collection to a single value by iteratively combining each |
130 * element of the collection with an existing value using the provided | 254 * element of the collection with an existing value |
131 * function. | |
132 * | 255 * |
133 * Use [initialValue] as the initial value, and the function [combine] to | 256 * Uses [initialValue] as the initial value, |
134 * create a new value from the previous one and an element. | 257 * then iterates through the elements and updates the value with |
| 258 * each element using the [combine] function, as if by: |
| 259 * |
| 260 * var value = initialValue; |
| 261 * for (E element in this) { |
| 262 * value = combine(value, element); |
| 263 * } |
| 264 * return value; |
135 * | 265 * |
136 * Example of calculating the sum of an iterable: | 266 * Example of calculating the sum of an iterable: |
137 * | 267 * |
138 * iterable.fold(0, (prev, element) => prev + element); | 268 * iterable.fold(0, (prev, element) => prev + element); |
139 * | 269 * |
140 */ | 270 */ |
141 dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue, | 271 dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue, |
142 dynamic/*=T*/ combine(var/*=T*/ previousValue, E element)); | 272 dynamic/*=T*/ combine(var/*=T*/ previousValue, E element)) { |
143 | 273 var value = initialValue; |
144 /** | 274 for (E element in this) value = combine(value, element); |
145 * Returns true if every elements of this collection satisify the | 275 return value; |
146 * predicate [test]. Returns `false` otherwise. | 276 } |
147 */ | 277 |
148 bool every(bool test(E element)); | 278 /** |
| 279 * Checks whether every element of this iterable satisfies [test]. |
| 280 * |
| 281 * Checks every element in iteration order, and returns `false` if |
| 282 * any of them make [test] return `false`, otherwise returns `true`. |
| 283 */ |
| 284 bool every(bool f(E element)) { |
| 285 for (E element in this) { |
| 286 if (!f(element)) return false; |
| 287 } |
| 288 return true; |
| 289 } |
149 | 290 |
150 /** | 291 /** |
151 * Converts each element to a [String] and concatenates the strings. | 292 * Converts each element to a [String] and concatenates the strings. |
152 * | 293 * |
153 * Converts each element to a [String] by calling [Object.toString] on it. | 294 * Iterates through elements of this iterable, |
154 * Then concatenates the strings, optionally separated by the [separator] | 295 * converts each one to a [String] by calling [Object.toString], |
155 * string. | 296 * and then concatenates the strings, with the |
| 297 * [separator] string interleaved between the elements. |
156 */ | 298 */ |
157 String join([String separator = ""]) { | 299 String join([String separator = ""]) { |
| 300 Iterator<E> iterator = this.iterator; |
| 301 if (!iterator.moveNext()) return ""; |
158 StringBuffer buffer = new StringBuffer(); | 302 StringBuffer buffer = new StringBuffer(); |
159 buffer.writeAll(this, separator); | 303 if (separator == null || separator == "") { |
| 304 do { |
| 305 buffer.write("${iterator.current}"); |
| 306 } while (iterator.moveNext()); |
| 307 } else { |
| 308 buffer.write("${iterator.current}"); |
| 309 while (iterator.moveNext()) { |
| 310 buffer.write(separator); |
| 311 buffer.write("${iterator.current}"); |
| 312 } |
| 313 } |
160 return buffer.toString(); | 314 return buffer.toString(); |
161 } | 315 } |
162 | 316 |
163 /** | 317 |
164 * Returns true if one element of this collection satisfies the | 318 /** |
165 * predicate [test]. Returns false otherwise. | 319 * Checks whether any element of this iterable satisfies [test]. |
166 */ | 320 * |
167 bool any(bool test(E element)); | 321 * Checks every element in iteration order, and returns `true` if |
| 322 * any of them make [test] return `true`, otherwise returns false. |
| 323 */ |
| 324 bool any(bool f(E element)) { |
| 325 for (E element in this) { |
| 326 if (f(element)) return true; |
| 327 } |
| 328 return false; |
| 329 } |
168 | 330 |
169 /** | 331 /** |
170 * Creates a [List] containing the elements of this [Iterable]. | 332 * Creates a [List] containing the elements of this [Iterable]. |
171 * | 333 * |
172 * The elements are in iteration order. The list is fixed-length | 334 * The elements are in iteration order. |
173 * if [growable] is false. | 335 * The list is fixed-length if [growable] is false. |
174 */ | 336 */ |
175 List<E> toList({ bool growable: true }); | 337 List<E> toList({ bool growable: true }) => |
| 338 new List<E>.from(this, growable: growable); |
176 | 339 |
177 /** | 340 /** |
178 * Creates a [Set] containing the same elements as this iterable. | 341 * Creates a [Set] containing the same elements as this iterable. |
179 * | 342 * |
180 * The set may contain fewer elements than the iterable, | 343 * The set may contain fewer elements than the iterable, |
181 * if the iterable contains the an element more than once, | 344 * if the iterable contains an element more than once, |
182 * or it contains one or more elements that are equal. | 345 * or it contains one or more elements that are equal. |
183 * The order of the elements in the set is not guaranteed to be the same | 346 * The order of the elements in the set is not guaranteed to be the same |
184 * as for the iterable. | 347 * as for the iterable. |
185 */ | 348 */ |
186 Set<E> toSet(); | 349 Set<E> toSet() => new Set<E>.from(this); |
187 | 350 |
188 /** | 351 /** |
189 * Returns the number of elements in [this]. | 352 * Returns the number of elements in [this]. |
190 * | 353 * |
191 * Counting all elements may be involve running through all elements and can | 354 * Counting all elements may involve iterating through all elements and can |
192 * therefore be slow. | 355 * therefore be slow. |
193 */ | 356 * Some iterables have a more efficient way to find the number of elements. |
194 int get length; | 357 */ |
195 | 358 int get length { |
196 /** | 359 assert(this is! EfficientLength); |
197 * Returns true if there is no element in this collection. | 360 int count = 0; |
198 */ | 361 Iterator it = iterator; |
199 bool get isEmpty; | 362 while (it.moveNext()) { |
| 363 count++; |
| 364 } |
| 365 return count; |
| 366 } |
| 367 |
| 368 /** |
| 369 * Returns `true` if there are no elements in this collection. |
| 370 * |
| 371 * May be computed by checking if `iterator.moveNext()` returns `false`. |
| 372 */ |
| 373 bool get isEmpty => !iterator.moveNext(); |
200 | 374 |
201 /** | 375 /** |
202 * Returns true if there is at least one element in this collection. | 376 * Returns true if there is at least one element in this collection. |
203 */ | 377 * |
204 bool get isNotEmpty; | 378 * May be computed by checking if `iterator.moveNext()` returns `true`. |
205 | 379 */ |
206 /** | 380 bool get isNotEmpty => !isEmpty; |
207 * Returns an [Iterable] with at most [count] elements. | 381 |
| 382 /** |
| 383 * Returns a lazy iterable of the [count] first elements of this iterable. |
208 * | 384 * |
209 * The returned `Iterable` may contain fewer than `count` elements, if `this` | 385 * The returned `Iterable` may contain fewer than `count` elements, if `this` |
210 * contains fewer than `count` elements. | 386 * contains fewer than `count` elements. |
211 * | 387 * |
212 * It is an error if `count` is negative. | 388 * The elements can be computed by stepping through [iterator] until [count] |
213 */ | 389 * elements have been seen. |
214 Iterable<E> take(int count); | 390 * |
215 | 391 * The `count` must not be negative. |
216 /** | 392 */ |
217 * Returns an Iterable that stops once [test] is not satisfied anymore. | 393 Iterable<E> take(int count) { |
218 * | 394 return new TakeIterable<E>(this, count); |
219 * The filtering happens lazily. Every new Iterator of the returned | 395 } |
220 * Iterable starts iterating over the elements of `this`. | 396 |
221 * | 397 /** |
222 * When the iterator encounters an element `e` that does not satisfy [test], | 398 * Returns a lazy iterable of the leading elements satisfying [test]. |
223 * it discards `e` and moves into the finished state. That is, it does not | 399 * |
224 * get or provide any more elements. | 400 * The filtering happens lazily. Every new iterator of the returned |
225 */ | 401 * iterable starts iterating over the elements of `this`. |
226 Iterable<E> takeWhile(bool test(E value)); | 402 * |
227 | 403 * The elements can be computed by stepping through [iterator] until an |
228 /** | 404 * element is found where `test(element)` is false. At that point, |
229 * Returns an Iterable that skips the first [count] elements. | 405 * the returned iterable stops (its `moveNext()` returns false). |
230 * | 406 */ |
| 407 Iterable<E> takeWhile(bool test(E value)) { |
| 408 return new TakeWhileIterable<E>(this, test); |
| 409 } |
| 410 |
| 411 /** |
| 412 * Returns an Iterable that provides all but the first [count] elements. |
| 413 * |
| 414 * When the returned iterable is iterated, it starts iterating over `this`, |
| 415 * first skipping past the initial [count] elements. |
231 * If `this` has fewer than `count` elements, then the resulting Iterable is | 416 * If `this` has fewer than `count` elements, then the resulting Iterable is |
232 * empty. | 417 * empty. |
233 * | 418 * After that, the remaining elements are iterated in the same order as |
234 * It is an error if `count` is negative. | 419 * in this iterable. |
235 */ | 420 * |
236 Iterable<E> skip(int count); | 421 * The `count` must not be negative. |
237 | 422 */ |
238 /** | 423 Iterable<E> skip(int count) { |
239 * Returns an Iterable that skips elements while [test] is satisfied. | 424 return new SkipIterable<E>(this, count); |
| 425 } |
| 426 |
| 427 /** |
| 428 * Returns an Iterable that skips leading elements while [test] is satisfied. |
240 * | 429 * |
241 * The filtering happens lazily. Every new Iterator of the returned | 430 * The filtering happens lazily. Every new Iterator of the returned |
242 * Iterable iterates over all elements of `this`. | 431 * Iterable iterates over all elements of `this`. |
243 * | 432 * |
244 * As long as the iterator's elements satisfy [test] they are | 433 * The returned iterable provides elements by iterating this iterable, |
245 * discarded. Once an element does not satisfy the [test] the iterator stops | 434 * but skipping over all initial elements where `test(element)` returns |
246 * testing and uses every later element unconditionally. That is, the elements | 435 * true. If all elements satisfy `test` the resulting iterable is empty, |
247 * of the returned Iterable are the elements of `this` starting from the | 436 * otherwise it iterates the remaining elements in their original order, |
248 * first element that does not satisfy [test]. | 437 * starting with the first element for which `test(element)` returns false, |
249 */ | 438 */ |
250 Iterable<E> skipWhile(bool test(E value)); | 439 Iterable<E> skipWhile(bool test(E value)) { |
| 440 return new SkipWhileIterable<E>(this, test); |
| 441 } |
251 | 442 |
252 /** | 443 /** |
253 * Returns the first element. | 444 * Returns the first element. |
254 * | 445 * |
255 * If `this` is empty throws a [StateError]. Otherwise this method is | 446 * Throws a [StateError] if `this` is empty. |
256 * equivalent to [:this.elementAt(0):] | 447 * Otherwise returns the first element in the iteration order, |
257 */ | 448 * equivalent to `this.elementAt(0)`. |
258 E get first; | 449 */ |
| 450 E get first { |
| 451 Iterator<E> it = iterator; |
| 452 if (!it.moveNext()) { |
| 453 throw IterableElementError.noElement(); |
| 454 } |
| 455 return it.current; |
| 456 } |
259 | 457 |
260 /** | 458 /** |
261 * Returns the last element. | 459 * Returns the last element. |
262 * | 460 * |
263 * If `this` is empty throws a [StateError]. | 461 * Throws a [StateError] if `this` is empty. |
264 */ | 462 * Otherwise may iterate through the elements and returns the last one |
265 E get last; | 463 * seen. |
266 | 464 * Some iterables may have more efficient ways to find the last element |
267 /** | 465 * (for example a list can directly access the last element, |
268 * Returns the single element in `this`. | 466 * without iterating through the previous ones). |
269 * | 467 */ |
270 * If `this` is empty or has more than one element throws a [StateError]. | 468 E get last { |
271 */ | 469 Iterator<E> it = iterator; |
272 E get single; | 470 if (!it.moveNext()) { |
| 471 throw IterableElementError.noElement(); |
| 472 } |
| 473 E result; |
| 474 do { |
| 475 result = it.current; |
| 476 } while(it.moveNext()); |
| 477 return result; |
| 478 } |
| 479 |
| 480 /** |
| 481 * Checks that this iterable has only one element, and returns that element. |
| 482 * |
| 483 * Throws a [StateError] if `this` is empty or has more than one element. |
| 484 */ |
| 485 E get single { |
| 486 Iterator<E> it = iterator; |
| 487 if (!it.moveNext()) throw IterableElementError.noElement(); |
| 488 E result = it.current; |
| 489 if (it.moveNext()) throw IterableElementError.tooMany(); |
| 490 return result; |
| 491 } |
273 | 492 |
274 /** | 493 /** |
275 * Returns the first element that satisfies the given predicate [test]. | 494 * Returns the first element that satisfies the given predicate [test]. |
276 * | 495 * |
277 * If none matches, the result of invoking the [orElse] function is | 496 * Iterates through elements and returns the first to satsify [test]. |
278 * returned. By default, when [orElse] is `null`, a [StateError] is | 497 * |
279 * thrown. | 498 * If no element satisfies [test], the result of invoking the [orElse] |
280 */ | 499 * function is returned. |
281 E firstWhere(bool test(E element), { E orElse() }); | 500 * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| 501 */ |
| 502 E firstWhere(bool test(E element), { E orElse() }) { |
| 503 for (E element in this) { |
| 504 if (test(element)) return element; |
| 505 } |
| 506 if (orElse != null) return orElse(); |
| 507 throw IterableElementError.noElement(); |
| 508 } |
282 | 509 |
283 /** | 510 /** |
284 * Returns the last element that satisfies the given predicate [test]. | 511 * Returns the last element that satisfies the given predicate [test]. |
285 * | 512 * |
286 * If none matches, the result of invoking the [orElse] function is | 513 * An iterable that can access its elements directly may check its |
287 * returned. By default, when [orElse] is `null`, a [StateError] is | 514 * elements in any order (for example a list starts by checking the |
288 * thrown. | 515 * last element and then moves towards the start of the list). |
289 */ | 516 * The default implementation iterates elements in iteration order, |
290 E lastWhere(bool test(E element), {E orElse()}); | 517 * checks `test(element)` for each, |
291 | 518 * and finally returns that last one that matched. |
292 /** | 519 * |
293 * Returns the single element that satisfies [test]. If no or more than one | 520 * If no element satsfies [test], the result of invoking the [orElse] |
294 * element match then a [StateError] is thrown. | 521 * function is returned. |
295 */ | 522 * If [orElse] is omitted, it defaults to throwing a [StateError]. |
296 E singleWhere(bool test(E element)); | 523 */ |
| 524 E lastWhere(bool test(E element), {E orElse()}) { |
| 525 E result = null; |
| 526 bool foundMatching = false; |
| 527 for (E element in this) { |
| 528 if (test(element)) { |
| 529 result = element; |
| 530 foundMatching = true; |
| 531 } |
| 532 } |
| 533 if (foundMatching) return result; |
| 534 if (orElse != null) return orElse(); |
| 535 throw IterableElementError.noElement(); |
| 536 } |
| 537 |
| 538 /** |
| 539 * Returns the single element that satisfies [test]. |
| 540 * |
| 541 * Checks all elements to see if `test(element)` returns true. |
| 542 * If exactly one element satisfies [test], that element is returned. |
| 543 * Otherwise, if there are no matching elements, or if there is more than |
| 544 * one matching element, a [StateError] is thrown. |
| 545 */ |
| 546 E singleWhere(bool test(E element)) { |
| 547 E result = null; |
| 548 bool foundMatching = false; |
| 549 for (E element in this) { |
| 550 if (test(element)) { |
| 551 if (foundMatching) { |
| 552 throw IterableElementError.tooMany(); |
| 553 } |
| 554 result = element; |
| 555 foundMatching = true; |
| 556 } |
| 557 } |
| 558 if (foundMatching) return result; |
| 559 throw IterableElementError.noElement(); |
| 560 } |
297 | 561 |
298 /** | 562 /** |
299 * Returns the [index]th element. | 563 * Returns the [index]th element. |
300 * | 564 * |
301 * The [index] must be non-negative and less than [length]. | 565 * The [index] must be non-negative and less than [length]. |
302 * | 566 * Index zero represents the first element (so `iterable.elementAt(0)` is |
303 * Note: if `this` does not have a deterministic iteration order then the | 567 * equivalent to `iterable.first`). |
304 * function may simply return any element without any iteration if there are | 568 * |
305 * at least [index] elements in `this`. | 569 * May iterate through the elements in iteration order, skipping the |
306 */ | 570 * first `index` elements and returning the next. |
307 E elementAt(int index); | 571 * Some iterable may have more efficient ways to find the element. |
| 572 */ |
| 573 E elementAt(int index) { |
| 574 if (index is! int) throw new ArgumentError.notNull("index"); |
| 575 RangeError.checkNotNegative(index, "index"); |
| 576 int elementIndex = 0; |
| 577 for (E element in this) { |
| 578 if (index == elementIndex) return element; |
| 579 elementIndex++; |
| 580 } |
| 581 throw new RangeError.index(index, this, "index", null, elementIndex); |
| 582 } |
| 583 |
| 584 /** |
| 585 * Returns a string representation of (some of) the elements of `this`. |
| 586 * |
| 587 * Elements are represented by their own `toString` results. |
| 588 * |
| 589 * The default representation always contains the first three elements. |
| 590 * If there are less than a hundred elements in the iterable, it also |
| 591 * contains the last two elements. |
| 592 * |
| 593 * If the resulting string isn't above 80 characters, more elements are |
| 594 * included from the start of the iterable. |
| 595 * |
| 596 * The conversion may omit calling `toString` on some elements if they |
| 597 * are known to not occur in the output, and it may stop iterating after |
| 598 * a hundred elements. |
| 599 */ |
| 600 String toString() => IterableBase.iterableToShortString(this, '(', ')'); |
308 } | 601 } |
309 | 602 |
310 typedef E _Generator<E>(int index); | 603 typedef E _Generator<E>(int index); |
311 | 604 |
312 class _GeneratorIterable<E> extends IterableBase<E> | 605 class _GeneratorIterable<E> extends Iterable<E> |
313 implements EfficientLength { | 606 implements EfficientLength { |
314 final int _start; | 607 final int _start; |
315 final int _end; | 608 final int _end; |
316 final _Generator<E> _generator; | 609 final _Generator<E> _generator; |
| 610 |
| 611 /// Creates an iterable that builds the elements from a generator function. |
| 612 /// |
| 613 /// The [generator] may be null, in which case the default generator |
| 614 /// enumerating the integer positions is used. This means that [int] must |
| 615 /// be assignable to [E] when no generator is provided. In practice this means |
| 616 /// that the generator can only be emitted when [E] is equal to `dynamic`, |
| 617 /// `int`, or `num`. The constructor will check that the types match. |
317 _GeneratorIterable(this._end, E generator(int n)) | 618 _GeneratorIterable(this._end, E generator(int n)) |
318 : _start = 0, | 619 : _start = 0, |
319 _generator = (generator != null) ? generator : _id; | 620 // The `as` below is used as check to make sure that `int` is assignable |
| 621 // to [E]. |
| 622 _generator = (generator != null) ? generator : _id as _Generator<E>; |
320 | 623 |
321 _GeneratorIterable.slice(this._start, this._end, this._generator); | 624 _GeneratorIterable.slice(this._start, this._end, this._generator); |
322 | 625 |
323 Iterator<E> get iterator => | 626 Iterator<E> get iterator => |
324 new _GeneratorIterator<E>(_start, _end, _generator); | 627 new _GeneratorIterator<E>(_start, _end, _generator); |
325 int get length => _end - _start; | 628 int get length => _end - _start; |
326 | 629 |
327 Iterable<E> skip(int count) { | 630 Iterable<E> skip(int count) { |
328 RangeError.checkNotNegative(count, "count"); | 631 RangeError.checkNotNegative(count, "count"); |
329 if (count == 0) return this; | 632 if (count == 0) return this; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 */ | 673 */ |
371 abstract class BidirectionalIterator<E> implements Iterator<E> { | 674 abstract class BidirectionalIterator<E> implements Iterator<E> { |
372 /** | 675 /** |
373 * Move back to the previous element. | 676 * Move back to the previous element. |
374 * | 677 * |
375 * Returns true and updates [current] if successful. Returns false | 678 * Returns true and updates [current] if successful. Returns false |
376 * and sets [current] to null if there is no previous element. | 679 * and sets [current] to null if there is no previous element. |
377 */ | 680 */ |
378 bool movePrevious(); | 681 bool movePrevious(); |
379 } | 682 } |
OLD | NEW |