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._internal; | 5 part of dart._internal; |
6 | 6 |
7 /** | 7 /** |
8 * Marker interface for [Iterable] subclasses that have an efficient | 8 * Marker interface for [Iterable] subclasses that have an efficient |
9 * [length] implementation. | 9 * [length] implementation. |
10 */ | 10 */ |
11 abstract class EfficientLength { | 11 abstract class EfficientLength { |
12 /** | 12 /** |
13 * Returns the number of elements in the iterable. | 13 * Returns the number of elements in the iterable. |
14 * | 14 * |
15 * This is an efficient operation that doesn't require iterating through | 15 * This is an efficient operation that doesn't require iterating through |
16 * the elements. | 16 * the elements. |
17 */ | 17 */ |
18 int get length; | 18 int get length; |
19 } | 19 } |
20 | 20 |
21 /** | 21 /** |
22 * An [Iterable] for classes that have efficient [length] and [elementAt]. | 22 * An [Iterable] for classes that have efficient [length] and [elementAt]. |
23 * | 23 * |
24 * All other methods are implemented in terms of [length] and [elementAt], | 24 * All other methods are implemented in terms of [length] and [elementAt], |
25 * including [iterator]. | 25 * including [iterator]. |
26 */ | 26 */ |
27 abstract class ListIterable<E> extends IterableBase<E> | 27 abstract class ListIterable<E> extends IterableBase<E> |
28 implements EfficientLength { | 28 implements EfficientLength { |
29 int get length; | 29 int get length; |
30 E elementAt(int i); | 30 E elementAt(int i); |
31 | 31 |
32 const ListIterable(); | 32 const ListIterable(); |
33 | 33 |
34 Iterator<E> get iterator => new ListIterator<E>(this); | 34 Iterator<E> get iterator => new ListIterator<E>(this); |
35 | 35 |
36 void forEach(void action(E element)) { | 36 void forEach(void action(E element)) { |
37 int length = this.length; | 37 int length = this.length; |
38 for (int i = 0; i < length; i++) { | 38 for (int i = 0; i < length; i++) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
87 int length = this.length; | 87 int length = this.length; |
88 for (int i = 0; i < length; i++) { | 88 for (int i = 0; i < length; i++) { |
89 if (test(elementAt(i))) return true; | 89 if (test(elementAt(i))) return true; |
90 if (length != this.length) { | 90 if (length != this.length) { |
91 throw new ConcurrentModificationError(this); | 91 throw new ConcurrentModificationError(this); |
92 } | 92 } |
93 } | 93 } |
94 return false; | 94 return false; |
95 } | 95 } |
96 | 96 |
97 E firstWhere(bool test(E element), { E orElse() }) { | 97 E firstWhere(bool test(E element), {E orElse()}) { |
98 int length = this.length; | 98 int length = this.length; |
99 for (int i = 0; i < length; i++) { | 99 for (int i = 0; i < length; i++) { |
100 E element = elementAt(i); | 100 E element = elementAt(i); |
101 if (test(element)) return element; | 101 if (test(element)) return element; |
102 if (length != this.length) { | 102 if (length != this.length) { |
103 throw new ConcurrentModificationError(this); | 103 throw new ConcurrentModificationError(this); |
104 } | 104 } |
105 } | 105 } |
106 if (orElse != null) return orElse(); | 106 if (orElse != null) return orElse(); |
107 throw IterableElementError.noElement(); | 107 throw IterableElementError.noElement(); |
108 } | 108 } |
109 | 109 |
110 E lastWhere(bool test(E element), { E orElse() }) { | 110 E lastWhere(bool test(E element), {E orElse()}) { |
111 int length = this.length; | 111 int length = this.length; |
112 for (int i = length - 1; i >= 0; i--) { | 112 for (int i = length - 1; i >= 0; i--) { |
113 E element = elementAt(i); | 113 E element = elementAt(i); |
114 if (test(element)) return element; | 114 if (test(element)) return element; |
115 if (length != this.length) { | 115 if (length != this.length) { |
116 throw new ConcurrentModificationError(this); | 116 throw new ConcurrentModificationError(this); |
117 } | 117 } |
118 } | 118 } |
119 if (orElse != null) return orElse(); | 119 if (orElse != null) return orElse(); |
120 throw IterableElementError.noElement(); | 120 throw IterableElementError.noElement(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 if (length != this.length) { | 165 if (length != this.length) { |
166 throw new ConcurrentModificationError(this); | 166 throw new ConcurrentModificationError(this); |
167 } | 167 } |
168 } | 168 } |
169 return buffer.toString(); | 169 return buffer.toString(); |
170 } | 170 } |
171 } | 171 } |
172 | 172 |
173 Iterable<E> where(bool test(E element)) => super.where(test); | 173 Iterable<E> where(bool test(E element)) => super.where(test); |
174 | 174 |
175 Iterable/*<T>*/ map/*<T>*/(/*=T*/f(E element)) => new MappedListIterable<E, dy namic/*=T*/>(this, f); | 175 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => |
176 new MappedListIterable<E, dynamic/*=T*/ >(this, f); | |
Bob Nystrom
2016/03/18 00:34:51
The space after the comment looks wrong to me. Mig
Leaf
2016/03/18 00:48:22
Seems to be:
leafp-macbookpro:dev_compiler leafp$
| |
176 | 177 |
177 E reduce(E combine(var value, E element)) { | 178 E reduce(E combine(var value, E element)) { |
178 int length = this.length; | 179 int length = this.length; |
179 if (length == 0) throw IterableElementError.noElement(); | 180 if (length == 0) throw IterableElementError.noElement(); |
180 E value = elementAt(0); | 181 E value = elementAt(0); |
181 for (int i = 1; i < length; i++) { | 182 for (int i = 1; i < length; i++) { |
182 value = combine(value, elementAt(i)); | 183 value = combine(value, elementAt(i)); |
183 if (length != this.length) { | 184 if (length != this.length) { |
184 throw new ConcurrentModificationError(this); | 185 throw new ConcurrentModificationError(this); |
185 } | 186 } |
186 | |
187 } | 187 } |
188 return value; | 188 return value; |
189 } | 189 } |
190 | 190 |
191 /*=T*/ fold/*<T>*/(var/*=T*/ initialValue, /*=T*/combine(var/*=T*/ previousVal ue, E element)) { | 191 /*=T*/ fold/*<T>*/( |
192 var/*=T*/ initialValue, /*=T*/ combine( | |
193 var/*=T*/ previousValue, E element)) { | |
192 var value = initialValue; | 194 var value = initialValue; |
193 int length = this.length; | 195 int length = this.length; |
194 for (int i = 0; i < length; i++) { | 196 for (int i = 0; i < length; i++) { |
195 value = combine(value, elementAt(i)); | 197 value = combine(value, elementAt(i)); |
196 if (length != this.length) { | 198 if (length != this.length) { |
197 throw new ConcurrentModificationError(this); | 199 throw new ConcurrentModificationError(this); |
198 } | 200 } |
199 } | 201 } |
200 return value; | 202 return value; |
201 } | 203 } |
202 | 204 |
203 Iterable<E> skip(int count) => new SubListIterable<E>(this, count, null); | 205 Iterable<E> skip(int count) => new SubListIterable<E>(this, count, null); |
204 | 206 |
205 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); | 207 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); |
206 | 208 |
207 Iterable<E> take(int count) => new SubListIterable<E>(this, 0, count); | 209 Iterable<E> take(int count) => new SubListIterable<E>(this, 0, count); |
208 | 210 |
209 Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test); | 211 Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test); |
210 | 212 |
211 List<E> toList({ bool growable: true }) { | 213 List<E> toList({bool growable: true}) { |
212 List<E> result; | 214 List<E> result; |
213 if (growable) { | 215 if (growable) { |
214 result = new List<E>()..length = length; | 216 result = new List<E>()..length = length; |
215 } else { | 217 } else { |
216 result = new List<E>(length); | 218 result = new List<E>(length); |
217 } | 219 } |
218 for (int i = 0; i < length; i++) { | 220 for (int i = 0; i < length; i++) { |
219 result[i] = elementAt(i); | 221 result[i] = elementAt(i); |
220 } | 222 } |
221 return result; | 223 return result; |
222 } | 224 } |
223 | 225 |
224 Set<E> toSet() { | 226 Set<E> toSet() { |
225 Set<E> result = new Set<E>(); | 227 Set<E> result = new Set<E>(); |
226 for (int i = 0; i < length; i++) { | 228 for (int i = 0; i < length; i++) { |
227 result.add(elementAt(i)); | 229 result.add(elementAt(i)); |
228 } | 230 } |
229 return result; | 231 return result; |
230 } | 232 } |
231 } | 233 } |
232 | 234 |
233 class SubListIterable<E> extends ListIterable<E> { | 235 class SubListIterable<E> extends ListIterable<E> { |
234 final Iterable<E> _iterable; // Has efficient length and elementAt. | 236 final Iterable<E> _iterable; // Has efficient length and elementAt. |
235 final int _start; | 237 final int _start; |
236 /** If null, represents the length of the iterable. */ | 238 /** If null, represents the length of the iterable. */ |
237 final int _endOrLength; | 239 final int _endOrLength; |
238 | 240 |
239 SubListIterable(this._iterable, this._start, this._endOrLength) { | 241 SubListIterable(this._iterable, this._start, this._endOrLength) { |
240 RangeError.checkNotNegative(_start, "start"); | 242 RangeError.checkNotNegative(_start, "start"); |
241 if (_endOrLength != null) { | 243 if (_endOrLength != null) { |
242 RangeError.checkNotNegative(_endOrLength, "end"); | 244 RangeError.checkNotNegative(_endOrLength, "end"); |
243 if (_start > _endOrLength) { | 245 if (_start > _endOrLength) { |
244 throw new RangeError.range(_start, 0, _endOrLength, "start"); | 246 throw new RangeError.range(_start, 0, _endOrLength, "start"); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 return new SubListIterable<E>(_iterable, _start, newEnd); | 296 return new SubListIterable<E>(_iterable, _start, newEnd); |
295 } | 297 } |
296 } | 298 } |
297 | 299 |
298 List<E> toList({bool growable: true}) { | 300 List<E> toList({bool growable: true}) { |
299 int start = _start; | 301 int start = _start; |
300 int end = _iterable.length; | 302 int end = _iterable.length; |
301 if (_endOrLength != null && _endOrLength < end) end = _endOrLength; | 303 if (_endOrLength != null && _endOrLength < end) end = _endOrLength; |
302 int length = end - start; | 304 int length = end - start; |
303 if (length < 0) length = 0; | 305 if (length < 0) length = 0; |
304 List result = growable ? (new List<E>()..length = length) | 306 List result = |
305 : new List<E>(length); | 307 growable ? (new List<E>()..length = length) : new List<E>(length); |
306 for (int i = 0; i < length; i++) { | 308 for (int i = 0; i < length; i++) { |
307 result[i] = _iterable.elementAt(start + i); | 309 result[i] = _iterable.elementAt(start + i); |
308 if (_iterable.length < end) throw new ConcurrentModificationError(this); | 310 if (_iterable.length < end) throw new ConcurrentModificationError(this); |
309 } | 311 } |
310 return result; | 312 return result; |
311 } | 313 } |
312 } | 314 } |
313 | 315 |
314 /** | 316 /** |
315 * An [Iterator] that iterates a list-like [Iterable]. | 317 * An [Iterator] that iterates a list-like [Iterable]. |
316 * | 318 * |
317 * All iterations is done in terms of [Iterable.length] and | 319 * All iterations is done in terms of [Iterable.length] and |
318 * [Iterable.elementAt]. These operations are fast for list-like | 320 * [Iterable.elementAt]. These operations are fast for list-like |
319 * iterables. | 321 * iterables. |
320 */ | 322 */ |
321 class ListIterator<E> implements Iterator<E> { | 323 class ListIterator<E> implements Iterator<E> { |
322 final Iterable<E> _iterable; | 324 final Iterable<E> _iterable; |
323 final int _length; | 325 final int _length; |
324 int _index; | 326 int _index; |
325 E _current; | 327 E _current; |
326 | 328 |
327 ListIterator(Iterable<E> iterable) | 329 ListIterator(Iterable<E> iterable) |
328 : _iterable = iterable, _length = iterable.length, _index = 0; | 330 : _iterable = iterable, |
331 _length = iterable.length, | |
332 _index = 0; | |
329 | 333 |
330 E get current => _current; | 334 E get current => _current; |
331 | 335 |
332 bool moveNext() { | 336 bool moveNext() { |
333 int length = _iterable.length; | 337 int length = _iterable.length; |
334 if (_length != length) { | 338 if (_length != length) { |
335 throw new ConcurrentModificationError(_iterable); | 339 throw new ConcurrentModificationError(_iterable); |
336 } | 340 } |
337 if (_index >= length) { | 341 if (_index >= length) { |
338 _current = null; | 342 _current = null; |
(...skipping 27 matching lines...) Expand all Loading... | |
366 bool get isEmpty => _iterable.isEmpty; | 370 bool get isEmpty => _iterable.isEmpty; |
367 | 371 |
368 // Index based lookup can be done before transforming. | 372 // Index based lookup can be done before transforming. |
369 T get first => _f(_iterable.first); | 373 T get first => _f(_iterable.first); |
370 T get last => _f(_iterable.last); | 374 T get last => _f(_iterable.last); |
371 T get single => _f(_iterable.single); | 375 T get single => _f(_iterable.single); |
372 T elementAt(int index) => _f(_iterable.elementAt(index)); | 376 T elementAt(int index) => _f(_iterable.elementAt(index)); |
373 } | 377 } |
374 | 378 |
375 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T> | 379 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T> |
376 implements EfficientLength { | 380 implements EfficientLength { |
377 EfficientLengthMappedIterable(Iterable iterable, T function(S value)) | 381 EfficientLengthMappedIterable(Iterable iterable, T function(S value)) |
378 : super._(iterable, function); | 382 : super._(iterable, function); |
379 } | 383 } |
380 | 384 |
381 class MappedIterator<S, T> extends Iterator<T> { | 385 class MappedIterator<S, T> extends Iterator<T> { |
382 T _current; | 386 T _current; |
383 final Iterator<S> _iterator; | 387 final Iterator<S> _iterator; |
384 final _Transformation<S, T> _f; | 388 final _Transformation<S, T> _f; |
385 | 389 |
386 MappedIterator(this._iterator, T this._f(S element)); | 390 MappedIterator(this._iterator, T this._f(S element)); |
387 | 391 |
388 bool moveNext() { | 392 bool moveNext() { |
389 if (_iterator.moveNext()) { | 393 if (_iterator.moveNext()) { |
390 _current = _f(_iterator.current); | 394 _current = _f(_iterator.current); |
391 return true; | 395 return true; |
392 } | 396 } |
393 _current = null; | 397 _current = null; |
394 return false; | 398 return false; |
395 } | 399 } |
396 | 400 |
397 T get current => _current; | 401 T get current => _current; |
398 } | 402 } |
399 | 403 |
400 /** | 404 /** |
401 * Specialized alternative to [MappedIterable] for mapped [List]s. | 405 * Specialized alternative to [MappedIterable] for mapped [List]s. |
402 * | 406 * |
403 * Expects efficient `length` and `elementAt` on the source iterable. | 407 * Expects efficient `length` and `elementAt` on the source iterable. |
404 */ | 408 */ |
405 class MappedListIterable<S, T> extends ListIterable<T> | 409 class MappedListIterable<S, T> extends ListIterable<T> |
406 implements EfficientLength { | 410 implements EfficientLength { |
407 final Iterable<S> _source; | 411 final Iterable<S> _source; |
408 final _Transformation<S, T> _f; | 412 final _Transformation<S, T> _f; |
409 | 413 |
410 MappedListIterable(this._source, T this._f(S value)); | 414 MappedListIterable(this._source, T this._f(S value)); |
411 | 415 |
412 int get length => _source.length; | 416 int get length => _source.length; |
413 T elementAt(int index) => _f(_source.elementAt(index)); | 417 T elementAt(int index) => _f(_source.elementAt(index)); |
414 } | 418 } |
415 | 419 |
416 | |
417 typedef bool _ElementPredicate<E>(E element); | 420 typedef bool _ElementPredicate<E>(E element); |
418 | 421 |
419 class WhereIterable<E> extends IterableBase<E> { | 422 class WhereIterable<E> extends IterableBase<E> { |
420 final Iterable<E> _iterable; | 423 final Iterable<E> _iterable; |
421 final _ElementPredicate<E> _f; | 424 final _ElementPredicate<E> _f; |
422 | 425 |
423 WhereIterable(this._iterable, bool this._f(E element)); | 426 WhereIterable(this._iterable, bool this._f(E element)); |
424 | 427 |
425 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f); | 428 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f); |
426 } | 429 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 final Iterator<S> _iterator; | 461 final Iterator<S> _iterator; |
459 final _ExpandFunction _f; | 462 final _ExpandFunction _f; |
460 // Initialize _currentExpansion to an empty iterable. A null value | 463 // Initialize _currentExpansion to an empty iterable. A null value |
461 // marks the end of iteration, and we don't want to call _f before | 464 // marks the end of iteration, and we don't want to call _f before |
462 // the first moveNext call. | 465 // the first moveNext call. |
463 Iterator<T> _currentExpansion = const EmptyIterator(); | 466 Iterator<T> _currentExpansion = const EmptyIterator(); |
464 T _current; | 467 T _current; |
465 | 468 |
466 ExpandIterator(this._iterator, Iterable<T> this._f(S element)); | 469 ExpandIterator(this._iterator, Iterable<T> this._f(S element)); |
467 | 470 |
468 void _nextExpansion() { | 471 void _nextExpansion() {} |
469 } | |
470 | 472 |
471 T get current => _current; | 473 T get current => _current; |
472 | 474 |
473 bool moveNext() { | 475 bool moveNext() { |
474 if (_currentExpansion == null) return false; | 476 if (_currentExpansion == null) return false; |
475 while (!_currentExpansion.moveNext()) { | 477 while (!_currentExpansion.moveNext()) { |
476 _current = null; | 478 _current = null; |
477 if (_iterator.moveNext()) { | 479 if (_iterator.moveNext()) { |
478 // If _f throws, this ends iteration. Otherwise _currentExpansion and | 480 // If _f throws, this ends iteration. Otherwise _currentExpansion and |
479 // _current will be set again below. | 481 // _current will be set again below. |
(...skipping 23 matching lines...) Expand all Loading... | |
503 } | 505 } |
504 | 506 |
505 TakeIterable._(this._iterable, this._takeCount); | 507 TakeIterable._(this._iterable, this._takeCount); |
506 | 508 |
507 Iterator<E> get iterator { | 509 Iterator<E> get iterator { |
508 return new TakeIterator<E>(_iterable.iterator, _takeCount); | 510 return new TakeIterator<E>(_iterable.iterator, _takeCount); |
509 } | 511 } |
510 } | 512 } |
511 | 513 |
512 class EfficientLengthTakeIterable<E> extends TakeIterable<E> | 514 class EfficientLengthTakeIterable<E> extends TakeIterable<E> |
513 implements EfficientLength { | 515 implements EfficientLength { |
514 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) | 516 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) |
515 : super._(iterable, takeCount); | 517 : super._(iterable, takeCount); |
516 | 518 |
517 int get length { | 519 int get length { |
518 int iterableLength = _iterable.length; | 520 int iterableLength = _iterable.length; |
519 if (iterableLength > _takeCount) return _takeCount; | 521 if (iterableLength > _takeCount) return _takeCount; |
520 return iterableLength; | 522 return iterableLength; |
521 } | 523 } |
522 } | 524 } |
523 | 525 |
524 | |
525 class TakeIterator<E> extends Iterator<E> { | 526 class TakeIterator<E> extends Iterator<E> { |
526 final Iterator<E> _iterator; | 527 final Iterator<E> _iterator; |
527 int _remaining; | 528 int _remaining; |
528 | 529 |
529 TakeIterator(this._iterator, this._remaining) { | 530 TakeIterator(this._iterator, this._remaining) { |
530 assert(_remaining is int && _remaining >= 0); | 531 assert(_remaining is int && _remaining >= 0); |
531 } | 532 } |
532 | 533 |
533 bool moveNext() { | 534 bool moveNext() { |
534 _remaining--; | 535 _remaining--; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 RangeError.checkNotNegative(_skipCount, "count"); | 604 RangeError.checkNotNegative(_skipCount, "count"); |
604 return new SkipIterable<E>._(_iterable, _skipCount + count); | 605 return new SkipIterable<E>._(_iterable, _skipCount + count); |
605 } | 606 } |
606 | 607 |
607 Iterator<E> get iterator { | 608 Iterator<E> get iterator { |
608 return new SkipIterator<E>(_iterable.iterator, _skipCount); | 609 return new SkipIterator<E>(_iterable.iterator, _skipCount); |
609 } | 610 } |
610 } | 611 } |
611 | 612 |
612 class EfficientLengthSkipIterable<E> extends SkipIterable<E> | 613 class EfficientLengthSkipIterable<E> extends SkipIterable<E> |
613 implements EfficientLength { | 614 implements EfficientLength { |
614 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) | 615 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) |
615 : super._(iterable, skipCount); | 616 : super._(iterable, skipCount); |
616 | 617 |
617 int get length { | 618 int get length { |
618 int length = _iterable.length - _skipCount; | 619 int length = _iterable.length - _skipCount; |
619 if (length >= 0) return length; | 620 if (length >= 0) return length; |
620 return 0; | 621 return 0; |
621 } | 622 } |
622 } | 623 } |
623 | 624 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
676 const EmptyIterable(); | 677 const EmptyIterable(); |
677 | 678 |
678 Iterator<E> get iterator => const EmptyIterator(); | 679 Iterator<E> get iterator => const EmptyIterator(); |
679 | 680 |
680 void forEach(void action(E element)) {} | 681 void forEach(void action(E element)) {} |
681 | 682 |
682 bool get isEmpty => true; | 683 bool get isEmpty => true; |
683 | 684 |
684 int get length => 0; | 685 int get length => 0; |
685 | 686 |
686 E get first { throw IterableElementError.noElement(); } | 687 E get first { |
688 throw IterableElementError.noElement(); | |
689 } | |
687 | 690 |
688 E get last { throw IterableElementError.noElement(); } | 691 E get last { |
692 throw IterableElementError.noElement(); | |
693 } | |
689 | 694 |
690 E get single { throw IterableElementError.noElement(); } | 695 E get single { |
696 throw IterableElementError.noElement(); | |
697 } | |
691 | 698 |
692 E elementAt(int index) { throw new RangeError.range(index, 0, 0, "index"); } | 699 E elementAt(int index) { |
700 throw new RangeError.range(index, 0, 0, "index"); | |
701 } | |
693 | 702 |
694 bool contains(Object element) => false; | 703 bool contains(Object element) => false; |
695 | 704 |
696 bool every(bool test(E element)) => true; | 705 bool every(bool test(E element)) => true; |
697 | 706 |
698 bool any(bool test(E element)) => false; | 707 bool any(bool test(E element)) => false; |
699 | 708 |
700 E firstWhere(bool test(E element), { E orElse() }) { | 709 E firstWhere(bool test(E element), {E orElse()}) { |
701 if (orElse != null) return orElse(); | 710 if (orElse != null) return orElse(); |
702 throw IterableElementError.noElement(); | 711 throw IterableElementError.noElement(); |
703 } | 712 } |
704 | 713 |
705 E lastWhere(bool test(E element), { E orElse() }) { | 714 E lastWhere(bool test(E element), {E orElse()}) { |
706 if (orElse != null) return orElse(); | 715 if (orElse != null) return orElse(); |
707 throw IterableElementError.noElement(); | 716 throw IterableElementError.noElement(); |
708 } | 717 } |
709 | 718 |
710 E singleWhere(bool test(E element), { E orElse() }) { | 719 E singleWhere(bool test(E element), {E orElse()}) { |
711 if (orElse != null) return orElse(); | 720 if (orElse != null) return orElse(); |
712 throw IterableElementError.noElement(); | 721 throw IterableElementError.noElement(); |
713 } | 722 } |
714 | 723 |
715 String join([String separator = ""]) => ""; | 724 String join([String separator = ""]) => ""; |
716 | 725 |
717 Iterable<E> where(bool test(E element)) => this; | 726 Iterable<E> where(bool test(E element)) => this; |
718 | 727 |
719 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => const EmptyIterable(); | 728 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => const EmptyIterable(); |
720 | 729 |
721 E reduce(E combine(E value, E element)) { | 730 E reduce(E combine(E value, E element)) { |
722 throw IterableElementError.noElement(); | 731 throw IterableElementError.noElement(); |
723 } | 732 } |
724 | 733 |
725 /*=T*/ fold/*<T>*/(var/*=T*/ initialValue, /*=T*/ combine(var/*=T*/ previousVa lue, E element)) { | 734 /*=T*/ fold/*<T>*/( |
735 var/*=T*/ initialValue, /*=T*/ combine( | |
736 var/*=T*/ previousValue, E element)) { | |
726 return initialValue; | 737 return initialValue; |
727 } | 738 } |
728 | 739 |
729 Iterable<E> skip(int count) { | 740 Iterable<E> skip(int count) { |
730 RangeError.checkNotNegative(count, "count"); | 741 RangeError.checkNotNegative(count, "count"); |
731 return this; | 742 return this; |
732 } | 743 } |
733 | 744 |
734 Iterable<E> skipWhile(bool test(E element)) => this; | 745 Iterable<E> skipWhile(bool test(E element)) => this; |
735 | 746 |
736 Iterable<E> take(int count) { | 747 Iterable<E> take(int count) { |
737 RangeError.checkNotNegative(count, "count"); | 748 RangeError.checkNotNegative(count, "count"); |
738 return this; | 749 return this; |
739 } | 750 } |
740 | 751 |
741 Iterable<E> takeWhile(bool test(E element)) => this; | 752 Iterable<E> takeWhile(bool test(E element)) => this; |
742 | 753 |
743 List<E> toList({ bool growable: true }) => growable ? <E>[] : new List<E>(0); | 754 List<E> toList({bool growable: true}) => growable ? <E>[] : new List<E>(0); |
744 | 755 |
745 Set<E> toSet() => new Set<E>(); | 756 Set<E> toSet() => new Set<E>(); |
746 } | 757 } |
747 | 758 |
748 /** The always empty iterator. */ | 759 /** The always empty iterator. */ |
749 class EmptyIterator<E> implements Iterator<E> { | 760 class EmptyIterator<E> implements Iterator<E> { |
750 const EmptyIterator(); | 761 const EmptyIterator(); |
751 bool moveNext() => false; | 762 bool moveNext() => false; |
752 E get current => null; | 763 E get current => null; |
753 } | 764 } |
(...skipping 30 matching lines...) Expand all Loading... | |
784 } | 795 } |
785 | 796 |
786 static bool every/*<E>*/(Iterable/*<E>*/ iterable, bool f(/*=E*/ o)) { | 797 static bool every/*<E>*/(Iterable/*<E>*/ iterable, bool f(/*=E*/ o)) { |
787 for (final e in iterable) { | 798 for (final e in iterable) { |
788 if (!f(e)) return false; | 799 if (!f(e)) return false; |
789 } | 800 } |
790 return true; | 801 return true; |
791 } | 802 } |
792 | 803 |
793 static dynamic/*=E*/ reduce/*<E>*/(Iterable/*<E>*/ iterable, | 804 static dynamic/*=E*/ reduce/*<E>*/(Iterable/*<E>*/ iterable, |
794 dynamic/*=E*/ combine(/*=E*/previousValue, /*= E*/element)) { | 805 dynamic/*=E*/ combine(/*=E*/ previousValue, /*=E*/ element)) { |
795 Iterator/*<E>*/ iterator = iterable.iterator; | 806 Iterator/*<E>*/ iterator = iterable.iterator; |
796 if (!iterator.moveNext()) throw IterableElementError.noElement(); | 807 if (!iterator.moveNext()) throw IterableElementError.noElement(); |
797 var value = iterator.current; | 808 var value = iterator.current; |
798 while (iterator.moveNext()) { | 809 while (iterator.moveNext()) { |
799 value = combine(value, iterator.current); | 810 value = combine(value, iterator.current); |
800 } | 811 } |
801 return value; | 812 return value; |
802 } | 813 } |
803 | 814 |
804 static /*=V*/ fold/*<E, V>*/(Iterable/*<E>*/ iterable, | 815 static/*=V*/ fold/*<E, V>*/( |
805 dynamic/*=V*/ initialValue, | 816 Iterable/*<E>*/ iterable, |
806 dynamic/*=V*/ combine(dynamic/*=V*/ previousValue , /*=E*/element)) { | 817 dynamic/*=V*/ initialValue, |
818 dynamic/*=V*/ combine(dynamic/*=V*/ previousValue, /*=E*/ element)) { | |
807 for (final element in iterable) { | 819 for (final element in iterable) { |
808 initialValue = combine(initialValue, element); | 820 initialValue = combine(initialValue, element); |
809 } | 821 } |
810 return initialValue; | 822 return initialValue; |
811 } | 823 } |
812 | 824 |
813 /** | 825 /** |
814 * Removes elements matching [test] from [list]. | 826 * Removes elements matching [test] from [list]. |
815 * | 827 * |
816 * This is performed in two steps, to avoid exposing an inconsistent state | 828 * This is performed in two steps, to avoid exposing an inconsistent state |
817 * to the [test] function. First the elements to retain are found, and then | 829 * to the [test] function. First the elements to retain are found, and then |
818 * the original list is updated to contain those elements. | 830 * the original list is updated to contain those elements. |
819 */ | 831 */ |
820 static void removeWhereList/*<E>*/(List/*<E>*/ list, bool test(var/*=E*/ eleme nt)) { | 832 static void removeWhereList/*<E>*/( |
833 List/*<E>*/ list, bool test(var/*=E*/ element)) { | |
821 List/*<E>*/ retained = []; | 834 List/*<E>*/ retained = []; |
822 int length = list.length; | 835 int length = list.length; |
823 for (int i = 0; i < length; i++) { | 836 for (int i = 0; i < length; i++) { |
824 var element = list[i]; | 837 var element = list[i]; |
825 if (!test(element)) { | 838 if (!test(element)) { |
826 retained.add(element); | 839 retained.add(element); |
827 } | 840 } |
828 if (length != list.length) { | 841 if (length != list.length) { |
829 throw new ConcurrentModificationError(list); | 842 throw new ConcurrentModificationError(list); |
830 } | 843 } |
(...skipping 18 matching lines...) Expand all Loading... | |
849 } | 862 } |
850 | 863 |
851 static dynamic/*=E*/ last/*<E>*/(Iterable/*<E>*/ iterable) { | 864 static dynamic/*=E*/ last/*<E>*/(Iterable/*<E>*/ iterable) { |
852 Iterator/*<E>*/ it = iterable.iterator; | 865 Iterator/*<E>*/ it = iterable.iterator; |
853 if (!it.moveNext()) { | 866 if (!it.moveNext()) { |
854 throw IterableElementError.noElement(); | 867 throw IterableElementError.noElement(); |
855 } | 868 } |
856 var/*=E*/ result; | 869 var/*=E*/ result; |
857 do { | 870 do { |
858 result = it.current; | 871 result = it.current; |
859 } while(it.moveNext()); | 872 } while (it.moveNext()); |
860 return result; | 873 return result; |
861 } | 874 } |
862 | 875 |
863 static dynamic/*=E*/ single/*<E>*/(Iterable/*<E>*/ iterable) { | 876 static dynamic/*=E*/ single/*<E>*/(Iterable/*<E>*/ iterable) { |
864 Iterator/*<E>*/ it = iterable.iterator; | 877 Iterator/*<E>*/ it = iterable.iterator; |
865 if (!it.moveNext()) throw IterableElementError.noElement(); | 878 if (!it.moveNext()) throw IterableElementError.noElement(); |
866 var result = it.current; | 879 var result = it.current; |
867 if (it.moveNext()) throw IterableElementError.tooMany(); | 880 if (it.moveNext()) throw IterableElementError.tooMany(); |
868 return result; | 881 return result; |
869 } | 882 } |
870 | 883 |
871 static dynamic/*=E*/ firstWhere/*<E>*/(Iterable/*<E>*/ iterable, | 884 static dynamic/*=E*/ firstWhere/*<E>*/(Iterable/*<E>*/ iterable, |
872 bool test(dynamic/*=E*/ value), | 885 bool test(dynamic/*=E*/ value), dynamic/*=E*/ orElse()) { |
873 dynamic/*=E*/ orElse()) { | |
874 for (var element in iterable) { | 886 for (var element in iterable) { |
875 if (test(element)) return element; | 887 if (test(element)) return element; |
876 } | 888 } |
877 if (orElse != null) return orElse(); | 889 if (orElse != null) return orElse(); |
878 throw IterableElementError.noElement(); | 890 throw IterableElementError.noElement(); |
879 } | 891 } |
880 | 892 |
881 static dynamic/*=E*/ lastWhere/*<E>*/(Iterable/*<E>*/ iterable, | 893 static dynamic/*=E*/ lastWhere/*<E>*/(Iterable/*<E>*/ iterable, |
882 bool test(dynamic/*=E*/ value), | 894 bool test(dynamic/*=E*/ value), dynamic/*=E*/ orElse()) { |
883 dynamic/*=E*/ orElse()) { | |
884 dynamic/*=E*/ result = null; | 895 dynamic/*=E*/ result = null; |
885 bool foundMatching = false; | 896 bool foundMatching = false; |
886 for (var element in iterable) { | 897 for (var element in iterable) { |
887 if (test(element)) { | 898 if (test(element)) { |
888 result = element; | 899 result = element; |
889 foundMatching = true; | 900 foundMatching = true; |
890 } | 901 } |
891 } | 902 } |
892 if (foundMatching) return result; | 903 if (foundMatching) return result; |
893 if (orElse != null) return orElse(); | 904 if (orElse != null) return orElse(); |
894 throw IterableElementError.noElement(); | 905 throw IterableElementError.noElement(); |
895 } | 906 } |
896 | 907 |
897 static dynamic/*=E*/ lastWhereList/*<E>*/(List/*<E>*/ list, | 908 static dynamic/*=E*/ lastWhereList/*<E>*/(List/*<E>*/ list, |
898 bool test(dynamic/*=E*/ value), | 909 bool test(dynamic/*=E*/ value), dynamic/*=E*/ orElse()) { |
899 dynamic/*=E*/ orElse()) { | |
900 // TODO(floitsch): check that arguments are of correct type? | 910 // TODO(floitsch): check that arguments are of correct type? |
901 for (int i = list.length - 1; i >= 0; i--) { | 911 for (int i = list.length - 1; i >= 0; i--) { |
902 var element = list[i]; | 912 var element = list[i]; |
903 if (test(element)) return element; | 913 if (test(element)) return element; |
904 } | 914 } |
905 if (orElse != null) return orElse(); | 915 if (orElse != null) return orElse(); |
906 throw IterableElementError.noElement(); | 916 throw IterableElementError.noElement(); |
907 } | 917 } |
908 | 918 |
909 static dynamic/*=E*/ singleWhere/*<E>*/(Iterable/*<E>*/ iterable, bool test(dy namic/*=E*/ value)) { | 919 static dynamic/*=E*/ singleWhere/*<E>*/( |
920 Iterable/*<E>*/ iterable, bool test(dynamic/*=E*/ value)) { | |
910 dynamic/*=E*/ result = null; | 921 dynamic/*=E*/ result = null; |
911 bool foundMatching = false; | 922 bool foundMatching = false; |
912 for (var element in iterable) { | 923 for (var element in iterable) { |
913 if (test(element)) { | 924 if (test(element)) { |
914 if (foundMatching) { | 925 if (foundMatching) { |
915 throw IterableElementError.tooMany(); | 926 throw IterableElementError.tooMany(); |
916 } | 927 } |
917 result = element; | 928 result = element; |
918 foundMatching = true; | 929 foundMatching = true; |
919 } | 930 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
954 buffer.write(list[i]); | 965 buffer.write(list[i]); |
955 } | 966 } |
956 } | 967 } |
957 return buffer.toString(); | 968 return buffer.toString(); |
958 } | 969 } |
959 | 970 |
960 Iterable<T> where(Iterable<T> iterable, bool f(T element)) { | 971 Iterable<T> where(Iterable<T> iterable, bool f(T element)) { |
961 return new WhereIterable<T>(iterable, f); | 972 return new WhereIterable<T>(iterable, f); |
962 } | 973 } |
963 | 974 |
964 static Iterable/*<V>*/ map/*<E, V>*/(Iterable/*<E>*/ iterable, /*=V*/ f(var/*= E*/ element)) { | 975 static Iterable/*<V>*/ map/*<E, V>*/( |
976 Iterable/*<E>*/ iterable, /*=V*/ f(var/*=E*/ element)) { | |
965 return new MappedIterable/*<E, V>*/(iterable, f); | 977 return new MappedIterable/*<E, V>*/(iterable, f); |
966 } | 978 } |
967 | 979 |
968 static Iterable/*<V>*/ mapList/*<E, V>*/(List/*<E>*/ list, /*=V*/ f(var/*=E*/ element)) { | 980 static Iterable/*<V>*/ mapList/*<E, V>*/( |
981 List/*<E>*/ list, /*=V*/ f(var/*=E*/ element)) { | |
969 return new MappedListIterable/*<E, V>*/(list, f); | 982 return new MappedListIterable/*<E, V>*/(list, f); |
970 } | 983 } |
971 | 984 |
972 static Iterable/*<V>*/ expand/*<E, V>*/(Iterable/*<E>*/ iterable, Iterable/*<V >*/ f(var/*=E*/ element)) { | 985 static Iterable/*<V>*/ expand/*<E, V>*/( |
986 Iterable/*<E>*/ iterable, Iterable/*<V>*/ f(var/*=E*/ element)) { | |
973 return new ExpandIterable/*<E, V>*/(iterable, f); | 987 return new ExpandIterable/*<E, V>*/(iterable, f); |
974 } | 988 } |
975 | 989 |
976 Iterable<T> takeList(List list, int n) { | 990 Iterable<T> takeList(List list, int n) { |
977 // The generic type is currently lost. It will be fixed with mixins. | 991 // The generic type is currently lost. It will be fixed with mixins. |
978 return new SubListIterable<T>(list, 0, n); | 992 return new SubListIterable<T>(list, 0, n); |
979 } | 993 } |
980 | 994 |
981 Iterable<T> takeWhile(Iterable iterable, bool test(var value)) { | 995 Iterable<T> takeWhile(Iterable iterable, bool test(var value)) { |
982 // The generic type is currently lost. It will be fixed with mixins. | 996 // The generic type is currently lost. It will be fixed with mixins. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1026 static void _rangeCheck(List list, int start, int end) { | 1040 static void _rangeCheck(List list, int start, int end) { |
1027 RangeError.checkValidRange(start, end, list.length); | 1041 RangeError.checkValidRange(start, end, list.length); |
1028 } | 1042 } |
1029 | 1043 |
1030 Iterable<T> getRangeList(List list, int start, int end) { | 1044 Iterable<T> getRangeList(List list, int start, int end) { |
1031 _rangeCheck(list, start, end); | 1045 _rangeCheck(list, start, end); |
1032 // The generic type is currently lost. It will be fixed with mixins. | 1046 // The generic type is currently lost. It will be fixed with mixins. |
1033 return new SubListIterable<T>(list, start, end); | 1047 return new SubListIterable<T>(list, start, end); |
1034 } | 1048 } |
1035 | 1049 |
1036 static void setRangeList(List list, int start, int end, | 1050 static void setRangeList( |
1037 Iterable from, int skipCount) { | 1051 List list, int start, int end, Iterable from, int skipCount) { |
1038 _rangeCheck(list, start, end); | 1052 _rangeCheck(list, start, end); |
1039 int length = end - start; | 1053 int length = end - start; |
1040 if (length == 0) return; | 1054 if (length == 0) return; |
1041 | 1055 |
1042 if (skipCount < 0) throw new ArgumentError(skipCount); | 1056 if (skipCount < 0) throw new ArgumentError(skipCount); |
1043 | 1057 |
1044 // TODO(floitsch): Make this accept more. | 1058 // TODO(floitsch): Make this accept more. |
1045 List otherList; | 1059 List otherList; |
1046 int otherStart; | 1060 int otherStart; |
1047 if (from is List) { | 1061 if (from is List) { |
1048 otherList = from; | 1062 otherList = from; |
1049 otherStart = skipCount; | 1063 otherStart = skipCount; |
1050 } else { | 1064 } else { |
1051 otherList = from.skip(skipCount).toList(growable: false); | 1065 otherList = from.skip(skipCount).toList(growable: false); |
1052 otherStart = 0; | 1066 otherStart = 0; |
1053 } | 1067 } |
1054 if (otherStart + length > otherList.length) { | 1068 if (otherStart + length > otherList.length) { |
1055 throw IterableElementError.tooFew(); | 1069 throw IterableElementError.tooFew(); |
1056 } | 1070 } |
1057 Lists.copy(otherList, otherStart, list, start, length); | 1071 Lists.copy(otherList, otherStart, list, start, length); |
1058 } | 1072 } |
1059 | 1073 |
1060 static void replaceRangeList(List list, int start, int end, | 1074 static void replaceRangeList( |
1061 Iterable iterable) { | 1075 List list, int start, int end, Iterable iterable) { |
1062 _rangeCheck(list, start, end); | 1076 _rangeCheck(list, start, end); |
1063 if (iterable is! EfficientLength) { | 1077 if (iterable is! EfficientLength) { |
1064 iterable = iterable.toList(); | 1078 iterable = iterable.toList(); |
1065 } | 1079 } |
1066 int removeLength = end - start; | 1080 int removeLength = end - start; |
1067 int insertLength = iterable.length; | 1081 int insertLength = iterable.length; |
1068 if (removeLength >= insertLength) { | 1082 if (removeLength >= insertLength) { |
1069 int delta = removeLength - insertLength; | 1083 int delta = removeLength - insertLength; |
1070 int insertEnd = start + insertLength; | 1084 int insertEnd = start + insertLength; |
1071 int newEnd = list.length - delta; | 1085 int newEnd = list.length - delta; |
1072 list.setRange(start, insertEnd, iterable); | 1086 list.setRange(start, insertEnd, iterable); |
1073 if (delta != 0) { | 1087 if (delta != 0) { |
1074 list.setRange(insertEnd, newEnd, list, end); | 1088 list.setRange(insertEnd, newEnd, list, end); |
1075 list.length = newEnd; | 1089 list.length = newEnd; |
1076 } | 1090 } |
1077 } else { | 1091 } else { |
1078 int delta = insertLength - removeLength; | 1092 int delta = insertLength - removeLength; |
1079 int newLength = list.length + delta; | 1093 int newLength = list.length + delta; |
1080 int insertEnd = start + insertLength; // aka. end + delta. | 1094 int insertEnd = start + insertLength; // aka. end + delta. |
1081 list.length = newLength; | 1095 list.length = newLength; |
1082 list.setRange(insertEnd, newLength, list, end); | 1096 list.setRange(insertEnd, newLength, list, end); |
1083 list.setRange(start, insertEnd, iterable); | 1097 list.setRange(start, insertEnd, iterable); |
1084 } | 1098 } |
1085 } | 1099 } |
1086 | 1100 |
1087 static void fillRangeList(List list, int start, int end, fillValue) { | 1101 static void fillRangeList(List list, int start, int end, fillValue) { |
1088 _rangeCheck(list, start, end); | 1102 _rangeCheck(list, start, end); |
1089 for (int i = start; i < end; i++) { | 1103 for (int i = start; i < end; i++) { |
1090 list[i] = fillValue; | 1104 list[i] = fillValue; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1160 * Creates errors throw by [Iterable] when the element count is wrong. | 1174 * Creates errors throw by [Iterable] when the element count is wrong. |
1161 */ | 1175 */ |
1162 abstract class IterableElementError { | 1176 abstract class IterableElementError { |
1163 /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ | 1177 /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ |
1164 static StateError noElement() => new StateError("No element"); | 1178 static StateError noElement() => new StateError("No element"); |
1165 /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ | 1179 /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ |
1166 static StateError tooMany() => new StateError("Too many elements"); | 1180 static StateError tooMany() => new StateError("Too many elements"); |
1167 /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ | 1181 /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ |
1168 static StateError tooFew() => new StateError("Too few elements"); | 1182 static StateError tooFew() => new StateError("Too few elements"); |
1169 } | 1183 } |
OLD | NEW |