Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/lib/core/iterable.dart

Issue 2698353003: unfork DDC's copy of most SDK libraries (Closed)
Patch Set: revert core_patch Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.core;
6
7 /**
8 * A collection of values, or "elements", that can be accessed sequentially.
9 *
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.
12 * Stepping with the iterator is done by calling [Iterator.moveNext],
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.
32 *
33 * Map kidsBooks = {'Matilda': 'Roald Dahl',
34 * 'Green Eggs and Ham': 'Dr Seuss',
35 * 'Where the Wild Things Are': 'Maurice Sendak'};
36 * for (var book in kidsBooks.keys) {
37 * print('$book was written by ${kidsBooks[book]}');
38 * }
39 *
40 * The [List] and [Set] classes are both `Iterable`,
41 * as are most classes in the [dart:collection](#dart-collection) library.
42 *
43 * Some [Iterable] collections can be modified.
44 * Adding an element to a `List` or `Set` will change which elements it
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).
50 *
51 * Changing a collection *while* it is being iterated
52 * is generally *not* allowed.
53 * Doing so will break the iteration, which is typically signalled
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.
81 */
82 abstract class Iterable<E> {
83 const Iterable();
84
85 /**
86 * Creates an `Iterable` that generates its elements dynamically.
87 *
88 * An `Iterator` created by [iterator] will count from
89 * zero to [:count - 1:], and call [generator]
90 * with each index in turn to create the next value.
91 *
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
94 * parameter allows integer values.
95 *
96 * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to
97 * `const [0, ..., n - 1].map(generator)`.
98 */
99 factory Iterable.generate(int count, [E generator(int index)]) {
100 if (count <= 0) return new EmptyIterable<E>();
101 return new _GeneratorIterable<E>(count, generator);
102 }
103
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 /**
113 * Returns a new `Iterator` that allows iterating the elements of this
114 * `Iterable`.
115 *
116 * Iterable classes may specify the iteration order of their elements
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.
139 */
140 Iterator<E> get iterator;
141
142 /**
143 * Returns a new lazy [Iterable] with elements that are created by
144 * calling `f` on each element of this `Iterable` in iteration order.
145 *
146 * This method returns a view of the mapped elements. As long as the
147 * returned [Iterable] is not iterated over, the supplied function [f] will
148 * not be invoked. The transformed elements will not be cached. Iterating
149 * multiple times over the returned [Iterable] will invoke the supplied
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.
155 */
156 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E e)) =>
157 new MappedIterable<E, dynamic/*=T*/>(this, f);
158
159 /**
160 * Returns a new lazy [Iterable] with all elements that satisfy the
161 * predicate [test].
162 *
163 * The matching elements have the same order in the returned iterable
164 * as they have in [iterator].
165 *
166 * This method returns a view of the mapped elements. As long as the
167 * returned [Iterable] is not iterated over, the supplied function [test] will
168 * not be invoked. Iterating will not cache results, and thus iterating
169 * multiple times over the returned [Iterable] will invoke the supplied
170 * function [test] multiple times on the same element.
171 */
172 Iterable<E> where(bool test(E element)) =>
173 new WhereIterable<E>(this, test);
174
175 /**
176 * Expands each element of this [Iterable] into zero or more elements.
177 *
178 * The resulting Iterable runs through the elements returned
179 * by [f] for each element of this, in iteration order.
180 *
181 * The returned [Iterable] is lazy, and calls [f] for each element
182 * of this every time it's iterated.
183 */
184 Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element)) =>
185 new ExpandIterable<E, dynamic/*=T*/>(this, f);
186
187 /**
188 * Returns true if the collection contains an element equal to [element].
189 *
190 * This operation will check each element in order for being equal to
191 * [element], unless it has a more efficient way to find an element
192 * equal to [element].
193 *
194 * The equality used to determine whether [element] is equal to an element of
195 * the iterable defaults to the [Object.operator==] of the element.
196 *
197 * Some types of iterable may have a different equality used for its elements.
198 * For example, a [Set] may have a custom equality
199 * (see [Set.identical]) that its `contains` uses.
200 * Likewise the `Iterable` returned by a [Map.keys] call
201 * should use the same equality that the `Map` uses for keys.
202 */
203 bool contains(Object element) {
204 for (E e in this) {
205 if (e == element) return true;
206 }
207 return false;
208 }
209
210
211 /**
212 * Applies the function [f] to each element of this collection in iteration
213 * order.
214 */
215 void forEach(void f(E element)) {
216 for (E element in this) f(element);
217 }
218
219 /**
220 * Reduces a collection to a single value by iteratively combining elements
221 * of the collection using the provided function.
222 *
223 * The iterable must have at least one element.
224 * If it has only one element, that element is returned.
225 *
226 * Otherwise this method starts with the first element from the iterator,
227 * and then combines it with the remaining elements in iteration order,
228 * as if by:
229 *
230 * E value = iterable.first;
231 * iterable.skip(1).forEach((element) {
232 * value = combine(value, element);
233 * });
234 * return value;
235 *
236 * Example of calculating the sum of an iterable:
237 *
238 * iterable.reduce((value, element) => value + element);
239 *
240 */
241 E reduce(E combine(E value, E element)) {
242 Iterator<E> iterator = this.iterator;
243 if (!iterator.moveNext()) {
244 throw IterableElementError.noElement();
245 }
246 E value = iterator.current;
247 while (iterator.moveNext()) {
248 value = combine(value, iterator.current);
249 }
250 return value;
251 }
252
253 /**
254 * Reduces a collection to a single value by iteratively combining each
255 * element of the collection with an existing value
256 *
257 * Uses [initialValue] as the initial value,
258 * then iterates through the elements and updates the value with
259 * each element using the [combine] function, as if by:
260 *
261 * var value = initialValue;
262 * for (E element in this) {
263 * value = combine(value, element);
264 * }
265 * return value;
266 *
267 * Example of calculating the sum of an iterable:
268 *
269 * iterable.fold(0, (prev, element) => prev + element);
270 *
271 */
272 dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue,
273 dynamic/*=T*/ combine(var/*=T*/ previousValue, E element)) {
274 var value = initialValue;
275 for (E element in this) value = combine(value, element);
276 return value;
277 }
278
279 /**
280 * Checks whether every element of this iterable satisfies [test].
281 *
282 * Checks every element in iteration order, and returns `false` if
283 * any of them make [test] return `false`, otherwise returns `true`.
284 */
285 bool every(bool f(E element)) {
286 for (E element in this) {
287 if (!f(element)) return false;
288 }
289 return true;
290 }
291
292 /**
293 * Converts each element to a [String] and concatenates the strings.
294 *
295 * Iterates through elements of this iterable,
296 * converts each one to a [String] by calling [Object.toString],
297 * and then concatenates the strings, with the
298 * [separator] string interleaved between the elements.
299 */
300 String join([String separator = ""]) {
301 Iterator<E> iterator = this.iterator;
302 if (!iterator.moveNext()) return "";
303 StringBuffer buffer = new StringBuffer();
304 if (separator == null || separator == "") {
305 do {
306 buffer.write("${iterator.current}");
307 } while (iterator.moveNext());
308 } else {
309 buffer.write("${iterator.current}");
310 while (iterator.moveNext()) {
311 buffer.write(separator);
312 buffer.write("${iterator.current}");
313 }
314 }
315 return buffer.toString();
316 }
317
318
319 /**
320 * Checks whether any element of this iterable satisfies [test].
321 *
322 * Checks every element in iteration order, and returns `true` if
323 * any of them make [test] return `true`, otherwise returns false.
324 */
325 bool any(bool f(E element)) {
326 for (E element in this) {
327 if (f(element)) return true;
328 }
329 return false;
330 }
331
332 /**
333 * Creates a [List] containing the elements of this [Iterable].
334 *
335 * The elements are in iteration order.
336 * The list is fixed-length if [growable] is false.
337 */
338 List<E> toList({ bool growable: true }) =>
339 new List<E>.from(this, growable: growable);
340
341 /**
342 * Creates a [Set] containing the same elements as this iterable.
343 *
344 * The set may contain fewer elements than the iterable,
345 * if the iterable contains an element more than once,
346 * or it contains one or more elements that are equal.
347 * The order of the elements in the set is not guaranteed to be the same
348 * as for the iterable.
349 */
350 Set<E> toSet() => new Set<E>.from(this);
351
352 /**
353 * Returns the number of elements in [this].
354 *
355 * Counting all elements may involve iterating through all elements and can
356 * therefore be slow.
357 * Some iterables have a more efficient way to find the number of elements.
358 */
359 int get length {
360 assert(this is! EfficientLength);
361 int count = 0;
362 Iterator it = iterator;
363 while (it.moveNext()) {
364 count++;
365 }
366 return count;
367 }
368
369 /**
370 * Returns `true` if there are no elements in this collection.
371 *
372 * May be computed by checking if `iterator.moveNext()` returns `false`.
373 */
374 bool get isEmpty => !iterator.moveNext();
375
376 /**
377 * Returns true if there is at least one element in this collection.
378 *
379 * May be computed by checking if `iterator.moveNext()` returns `true`.
380 */
381 bool get isNotEmpty => !isEmpty;
382
383 /**
384 * Returns a lazy iterable of the [count] first elements of this iterable.
385 *
386 * The returned `Iterable` may contain fewer than `count` elements, if `this`
387 * contains fewer than `count` elements.
388 *
389 * The elements can be computed by stepping through [iterator] until [count]
390 * elements have been seen.
391 *
392 * The `count` must not be negative.
393 */
394 Iterable<E> take(int count) {
395 return new TakeIterable<E>(this, count);
396 }
397
398 /**
399 * Returns a lazy iterable of the leading elements satisfying [test].
400 *
401 * The filtering happens lazily. Every new iterator of the returned
402 * iterable starts iterating over the elements of `this`.
403 *
404 * The elements can be computed by stepping through [iterator] until an
405 * element is found where `test(element)` is false. At that point,
406 * the returned iterable stops (its `moveNext()` returns false).
407 */
408 Iterable<E> takeWhile(bool test(E value)) {
409 return new TakeWhileIterable<E>(this, test);
410 }
411
412 /**
413 * Returns an Iterable that provides all but the first [count] elements.
414 *
415 * When the returned iterable is iterated, it starts iterating over `this`,
416 * first skipping past the initial [count] elements.
417 * If `this` has fewer than `count` elements, then the resulting Iterable is
418 * empty.
419 * After that, the remaining elements are iterated in the same order as
420 * in this iterable.
421 *
422 * The `count` must not be negative.
423 */
424 Iterable<E> skip(int count) {
425 return new SkipIterable<E>(this, count);
426 }
427
428 /**
429 * Returns an Iterable that skips leading elements while [test] is satisfied.
430 *
431 * The filtering happens lazily. Every new Iterator of the returned
432 * Iterable iterates over all elements of `this`.
433 *
434 * The returned iterable provides elements by iterating this iterable,
435 * but skipping over all initial elements where `test(element)` returns
436 * true. If all elements satisfy `test` the resulting iterable is empty,
437 * otherwise it iterates the remaining elements in their original order,
438 * starting with the first element for which `test(element)` returns false.
439 */
440 Iterable<E> skipWhile(bool test(E value)) {
441 return new SkipWhileIterable<E>(this, test);
442 }
443
444 /**
445 * Returns the first element.
446 *
447 * Throws a [StateError] if `this` is empty.
448 * Otherwise returns the first element in the iteration order,
449 * equivalent to `this.elementAt(0)`.
450 */
451 E get first {
452 Iterator<E> it = iterator;
453 if (!it.moveNext()) {
454 throw IterableElementError.noElement();
455 }
456 return it.current;
457 }
458
459 /**
460 * Returns the last element.
461 *
462 * Throws a [StateError] if `this` is empty.
463 * Otherwise may iterate through the elements and returns the last one
464 * seen.
465 * Some iterables may have more efficient ways to find the last element
466 * (for example a list can directly access the last element,
467 * without iterating through the previous ones).
468 */
469 E get last {
470 Iterator<E> it = iterator;
471 if (!it.moveNext()) {
472 throw IterableElementError.noElement();
473 }
474 E result;
475 do {
476 result = it.current;
477 } while(it.moveNext());
478 return result;
479 }
480
481 /**
482 * Checks that this iterable has only one element, and returns that element.
483 *
484 * Throws a [StateError] if `this` is empty or has more than one element.
485 */
486 E get single {
487 Iterator<E> it = iterator;
488 if (!it.moveNext()) throw IterableElementError.noElement();
489 E result = it.current;
490 if (it.moveNext()) throw IterableElementError.tooMany();
491 return result;
492 }
493
494 /**
495 * Returns the first element that satisfies the given predicate [test].
496 *
497 * Iterates through elements and returns the first to satsify [test].
498 *
499 * If no element satisfies [test], the result of invoking the [orElse]
500 * function is returned.
501 * If [orElse] is omitted, it defaults to throwing a [StateError].
502 */
503 E firstWhere(bool test(E element), { E orElse() }) {
504 for (E element in this) {
505 if (test(element)) return element;
506 }
507 if (orElse != null) return orElse();
508 throw IterableElementError.noElement();
509 }
510
511 /**
512 * Returns the last element that satisfies the given predicate [test].
513 *
514 * An iterable that can access its elements directly may check its
515 * elements in any order (for example a list starts by checking the
516 * last element and then moves towards the start of the list).
517 * The default implementation iterates elements in iteration order,
518 * checks `test(element)` for each,
519 * and finally returns that last one that matched.
520 *
521 * If no element satsfies [test], the result of invoking the [orElse]
522 * function is returned.
523 * If [orElse] is omitted, it defaults to throwing a [StateError].
524 */
525 E lastWhere(bool test(E element), {E orElse()}) {
526 E result = null;
527 bool foundMatching = false;
528 for (E element in this) {
529 if (test(element)) {
530 result = element;
531 foundMatching = true;
532 }
533 }
534 if (foundMatching) return result;
535 if (orElse != null) return orElse();
536 throw IterableElementError.noElement();
537 }
538
539 /**
540 * Returns the single element that satisfies [test].
541 *
542 * Checks all elements to see if `test(element)` returns true.
543 * If exactly one element satisfies [test], that element is returned.
544 * Otherwise, if there are no matching elements, or if there is more than
545 * one matching element, a [StateError] is thrown.
546 */
547 E singleWhere(bool test(E element)) {
548 E result = null;
549 bool foundMatching = false;
550 for (E element in this) {
551 if (test(element)) {
552 if (foundMatching) {
553 throw IterableElementError.tooMany();
554 }
555 result = element;
556 foundMatching = true;
557 }
558 }
559 if (foundMatching) return result;
560 throw IterableElementError.noElement();
561 }
562
563 /**
564 * Returns the [index]th element.
565 *
566 * The [index] must be non-negative and less than [length].
567 * Index zero represents the first element (so `iterable.elementAt(0)` is
568 * equivalent to `iterable.first`).
569 *
570 * May iterate through the elements in iteration order, skipping the
571 * first `index` elements and returning the next.
572 * Some iterable may have more efficient ways to find the element.
573 */
574 E elementAt(int index) {
575 if (index is! int) throw new ArgumentError.notNull("index");
576 RangeError.checkNotNegative(index, "index");
577 int elementIndex = 0;
578 for (E element in this) {
579 if (index == elementIndex) return element;
580 elementIndex++;
581 }
582 throw new RangeError.index(index, this, "index", null, elementIndex);
583 }
584
585 /**
586 * Returns a string representation of (some of) the elements of `this`.
587 *
588 * Elements are represented by their own `toString` results.
589 *
590 * The default representation always contains the first three elements.
591 * If there are less than a hundred elements in the iterable, it also
592 * contains the last two elements.
593 *
594 * If the resulting string isn't above 80 characters, more elements are
595 * included from the start of the iterable.
596 *
597 * 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
599 * a hundred elements.
600 */
601 String toString() => IterableBase.iterableToShortString(this, '(', ')');
602 }
603
604 typedef E _Generator<E>(int index);
605
606 class _GeneratorIterable<E> extends Iterable<E>
607 implements EfficientLength {
608 final int _start;
609 final int _end;
610 final _Generator<E> _generator;
611
612 /// Creates an iterable that builds the elements from a generator function.
613 ///
614 /// The [generator] may be null, in which case the default generator
615 /// enumerating the integer positions is used. This means that [int] must
616 /// be assignable to [E] when no generator is provided. In practice this means
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 _generator = (generator != null) ? generator : _id as _Generator<E>;
624
625 _GeneratorIterable.slice(this._start, this._end, this._generator);
626
627 Iterator<E> get iterator =>
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 }
638
639 Iterable<E> take(int count) {
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;
648 }
649
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 /**
673 * An Iterator that allows moving backwards as well as forwards.
674 */
675 abstract class BidirectionalIterator<E> implements Iterator<E> {
676 /**
677 * Move back to the previous element.
678 *
679 * Returns true and updates [current] if successful. Returns false
680 * and sets [current] to null if there is no previous element.
681 */
682 bool movePrevious();
683 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/lib/core/invocation.dart ('k') | pkg/dev_compiler/tool/input_sdk/lib/core/iterator.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698