| 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._collection.dev; | 5 part of dart._collection.dev; |
| 6 | 6 |
| 7 |
| 7 /** | 8 /** |
| 8 * An [Iterable] for classes that have efficient [length] and [elementAt]. | 9 * An [Iterable] for classes that have efficient [length] and [elementAt]. |
| 9 * | 10 * |
| 10 * All other methods are implemented in terms of [length] and [elementAt], | 11 * All other methods are implemented in terms of [length] and [elementAt], |
| 11 * including [iterator]. | 12 * including [iterator]. |
| 12 */ | 13 */ |
| 13 abstract class ListIterable<E> extends Iterable<E> { | 14 abstract class ListIterable<E> extends Iterable<E> { |
| 14 int get length; | 15 int get length; |
| 15 E elementAt(int i); | 16 E elementAt(int i); |
| 16 | 17 |
| 17 Iterator<E> get iterator => new ListIterator<E>(this); | 18 Iterator<E> get iterator => new ListIterableIterator<E>(this); |
| 18 | 19 |
| 19 void forEach(void action(E element)) { | 20 void forEach(void action(E element)) { |
| 20 int length = this.length; | 21 int length = this.length; |
| 21 for (int i = 0; i < length; i++) { | 22 for (int i = 0; i < length; i++) { |
| 22 action(elementAt(i)); | 23 action(elementAt(i)); |
| 23 if (length != this.length) { | 24 if (length != this.length) { |
| 24 throw new ConcurrentModificationError(this); | 25 throw new ConcurrentModificationError(this); |
| 25 } | 26 } |
| 26 } | 27 } |
| 27 } | 28 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 if (length != this.length) { | 86 if (length != this.length) { |
| 86 throw new ConcurrentModificationError(this); | 87 throw new ConcurrentModificationError(this); |
| 87 } | 88 } |
| 88 } | 89 } |
| 89 if (orElse != null) return orElse(); | 90 if (orElse != null) return orElse(); |
| 90 throw new StateError("No matching element"); | 91 throw new StateError("No matching element"); |
| 91 } | 92 } |
| 92 | 93 |
| 93 E lastMatching(bool test(E element), { E orElse() }) { | 94 E lastMatching(bool test(E element), { E orElse() }) { |
| 94 int length = this.length; | 95 int length = this.length; |
| 95 for (int i = length - 1; i >= 0; i--) { | 96 for (int i = length - 1; i >= 0; i++) { |
| 96 E element = elementAt(i); | 97 E element = elementAt(i); |
| 97 if (test(element)) return element; | 98 if (test(element)) return element; |
| 98 if (length != this.length) { | 99 if (length != this.length) { |
| 99 throw new ConcurrentModificationError(this); | 100 throw new ConcurrentModificationError(this); |
| 100 } | 101 } |
| 101 } | 102 } |
| 102 if (orElse != null) return orElse(); | 103 if (orElse != null) return orElse(); |
| 103 throw new StateError("No matching element"); | 104 throw new StateError("No matching element"); |
| 104 } | 105 } |
| 105 | 106 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 } | 191 } |
| 191 } | 192 } |
| 192 return buffer.toString(); | 193 return buffer.toString(); |
| 193 } | 194 } |
| 194 } | 195 } |
| 195 | 196 |
| 196 Iterable<E> where(bool test(E element)) => super.where(test); | 197 Iterable<E> where(bool test(E element)) => super.where(test); |
| 197 | 198 |
| 198 Iterable map(f(E element)) => new MappedIterable(this, f); | 199 Iterable map(f(E element)) => new MappedIterable(this, f); |
| 199 | 200 |
| 201 Iterable mappedBy(f(E element)) => super.mappedBy(f); |
| 202 |
| 200 reduce(var initialValue, combine(var previousValue, E element)) { | 203 reduce(var initialValue, combine(var previousValue, E element)) { |
| 201 var value = initialValue; | 204 var value = initialValue; |
| 202 int length = this.length; | 205 int length = this.length; |
| 203 for (int i = 0; i < length; i++) { | 206 for (int i = 0; i < length; i++) { |
| 204 value = combine(value, elementAt(i)); | 207 value = reduce(value, elementAt(i)); |
| 205 if (length != this.length) { | 208 if (length != this.length) { |
| 206 throw new ConcurrentModificationError(this); | 209 throw new ConcurrentModificationError(this); |
| 207 } | 210 } |
| 208 } | 211 } |
| 209 return value; | 212 return value; |
| 210 } | 213 } |
| 211 | 214 |
| 212 Iterable<E> skip(int count) => new SubListIterable(this, count, null); | 215 Iterable<E> skip(int count) => new SubListIterable(this, count, null); |
| 213 | 216 |
| 214 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); | 217 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 227 | 230 |
| 228 Set<E> toSet() { | 231 Set<E> toSet() { |
| 229 Set<E> result = new Set<E>(); | 232 Set<E> result = new Set<E>(); |
| 230 for (int i = 0; i < length; i++) { | 233 for (int i = 0; i < length; i++) { |
| 231 result.add(elementAt(i)); | 234 result.add(elementAt(i)); |
| 232 } | 235 } |
| 233 return result; | 236 return result; |
| 234 } | 237 } |
| 235 } | 238 } |
| 236 | 239 |
| 237 class SubListIterable<E> extends ListIterable<E> { | 240 abstract class SubListIterable<E> extends ListIterable<E> { |
| 238 final Iterable<E> _iterable; | 241 final Iterable<E> _iterable; |
| 239 final int _start; | 242 final int _start; |
| 240 /** If null, represents the length of the iterable. */ | 243 /** If null, represents the length of the iterable. */ |
| 241 final int _endOrLength; | 244 final int _endOrLength; |
| 242 | 245 |
| 243 SubListIterable(this._iterable, this._start, this._endOrLength); | 246 SubListIterable(this._iterable, this._start, this._endOrLength); |
| 244 | 247 |
| 245 int get _endIndex { | 248 int get _endIndex { |
| 246 int length = _iterable.length; | 249 int length = _iterable.length; |
| 247 if (_endOrLength == null || _endOrLength > length) return length; | 250 if (_endOrLength == null || _endOrLength > length) return length; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 274 Iterable<E> skip(int count) { | 277 Iterable<E> skip(int count) { |
| 275 if (count < 0) throw new ArgumentError(count); | 278 if (count < 0) throw new ArgumentError(count); |
| 276 return new SubListIterable(_iterable, _start + count, _endOrLength); | 279 return new SubListIterable(_iterable, _start + count, _endOrLength); |
| 277 } | 280 } |
| 278 | 281 |
| 279 Iterable<E> take(int count) { | 282 Iterable<E> take(int count) { |
| 280 if (count < 0) throw new ArgumentError(count); | 283 if (count < 0) throw new ArgumentError(count); |
| 281 if (_endOrLength == null) { | 284 if (_endOrLength == null) { |
| 282 return new SubListIterable(_iterable, _start, _start + count); | 285 return new SubListIterable(_iterable, _start, _start + count); |
| 283 } else { | 286 } else { |
| 284 int newEnd = _start + count; | 287 newEnd = _start + count; |
| 285 if (_endOrLength < newEnd) return this; | 288 if (_endOrLength < newEnd) return this; |
| 286 return new SubListIterable(_iterable, _start, newEnd); | 289 return new SubListIterable(_iterable, _start, newEnd); |
| 287 } | 290 } |
| 288 } | 291 } |
| 289 } | 292 } |
| 290 | 293 |
| 291 /** | 294 class ListIterableIterator<E> implements Iterator<E> { |
| 292 * An [Iterator] that iterates a list-like [Iterable]. | |
| 293 * | |
| 294 * All iterations is done in terms of [Iterable.length] and | |
| 295 * [Iterable.elementAt]. These operations are fast for list-like | |
| 296 * iterables. | |
| 297 */ | |
| 298 class ListIterator<E> implements Iterator<E> { | |
| 299 final Iterable<E> _iterable; | 295 final Iterable<E> _iterable; |
| 300 final int _length; | 296 final int _length; |
| 301 int _index; | 297 int _index; |
| 302 E _current; | 298 E _current; |
| 303 | 299 ListIterableIterator(Iterable<E> iterable) |
| 304 ListIterator(Iterable<E> iterable) | |
| 305 : _iterable = iterable, _length = iterable.length, _index = 0; | 300 : _iterable = iterable, _length = iterable.length, _index = 0; |
| 306 | 301 |
| 307 E get current => _current; | 302 E get current => _current; |
| 308 | 303 |
| 309 bool moveNext() { | 304 bool moveNext() { |
| 310 if (_length != _iterable.length) { | 305 if (_length != _iterable.length) { |
| 311 throw new ConcurrentModificationError(_iterable); | 306 throw new ConcurrentModificationError(_iterable); |
| 312 } | 307 } |
| 313 if (_index == _length) { | 308 if (_index == _length) { |
| 314 _current = null; | 309 _current = null; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 328 // checked mode. http://dartbug.com/7733 | 323 // checked mode. http://dartbug.com/7733 |
| 329 final /* _Transformation<S, T> */ _f; | 324 final /* _Transformation<S, T> */ _f; |
| 330 | 325 |
| 331 MappedIterable(this._iterable, T this._f(S element)); | 326 MappedIterable(this._iterable, T this._f(S element)); |
| 332 | 327 |
| 333 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); | 328 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); |
| 334 | 329 |
| 335 // Length related functions are independent of the mapping. | 330 // Length related functions are independent of the mapping. |
| 336 int get length => _iterable.length; | 331 int get length => _iterable.length; |
| 337 bool get isEmpty => _iterable.isEmpty; | 332 bool get isEmpty => _iterable.isEmpty; |
| 333 } |
| 338 | 334 |
| 339 // Index based lookup can be done before transforming. | |
| 340 T get first => _f(_iterable.first); | |
| 341 T get last => _f(_iterable.last); | |
| 342 T get single => _f(_iterable.single); | |
| 343 T elementAt(int index) => _f(_iterable.elementAt(index)); | |
| 344 } | |
| 345 | 335 |
| 346 class MappedIterator<S, T> extends Iterator<T> { | 336 class MappedIterator<S, T> extends Iterator<T> { |
| 347 T _current; | 337 T _current; |
| 348 final Iterator<S> _iterator; | 338 final Iterator<S> _iterator; |
| 349 // TODO(ahe): Restore type when feature is implemented in dart2js | 339 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 350 // checked mode. http://dartbug.com/7733 | 340 // checked mode. http://dartbug.com/7733 |
| 351 final /* _Transformation<S, T> */ _f; | 341 final /* _Transformation<S, T> */ _f; |
| 352 | 342 |
| 353 MappedIterator(this._iterator, T this._f(S element)); | 343 MappedIterator(this._iterator, T this._f(S element)); |
| 354 | 344 |
| 355 bool moveNext() { | 345 bool moveNext() { |
| 356 if (_iterator.moveNext()) { | 346 if (_iterator.moveNext()) { |
| 357 _current = _f(_iterator.current); | 347 _current = _f(_iterator.current); |
| 358 return true; | 348 return true; |
| 359 } | 349 } else { |
| 360 _current = null; | 350 _current = null; |
| 361 return false; | 351 return false; |
| 352 } |
| 362 } | 353 } |
| 363 | 354 |
| 364 T get current => _current; | 355 T get current => _current; |
| 365 } | 356 } |
| 366 | 357 |
| 367 /** Specialized alternative to [MappedIterable] for mapped [List]s. */ | 358 /** Specialized alternative to [MappedIterable] for mapped [List]s. */ |
| 368 class MappedListIterable<S, T> extends ListIterable<T> { | 359 class MappedListIterable<S, T> extends Iterable<T> { |
| 369 final Iterable<S> _source; | 360 final List<S> _list; |
| 361 /** |
| 362 * Start index of the part of the list to map. |
| 363 * |
| 364 * Allows mapping only a sub-list of an existing list. |
| 365 * |
| 366 * Used to implement lazy skip/take on a [MappedListIterable]. |
| 367 */ |
| 368 final int _start; |
| 369 |
| 370 /** |
| 371 * End index of the part of the list to map. |
| 372 * |
| 373 * If null, always use the length of the list. |
| 374 */ |
| 375 final int _end; |
| 376 |
| 370 // TODO(ahe): Restore type when feature is implemented in dart2js | 377 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 371 // checked mode. http://dartbug.com/7733 | 378 // checked mode. http://dartbug.com/7733 |
| 372 final /* _Transformation<S, T> */ _f; | 379 final /* _Transformation<S, T> */ _f; |
| 373 | 380 |
| 374 MappedListIterable(this._source, T this._f(S value)); | 381 MappedListIterable(this._list, T this._f(S element), this._start, this._end) { |
| 375 | 382 if (_end != null && _end < _start) { |
| 376 int get length => _source.length; | 383 throw new ArgumentError("End ($_end) before start ($_start)"); |
| 377 T elementAt(int index) => _f(_source.elementAt(index)); | 384 } |
| 385 } |
| 386 |
| 387 /** The start index, limited to the current length of the list. */ |
| 388 int get _startIndex { |
| 389 if (_start <= _list.length) return _start; |
| 390 return _list.length; |
| 391 } |
| 392 |
| 393 /** The end index, if given, limited to the current length of the list. */ |
| 394 int get _endIndex { |
| 395 if (_end == null || _end > _list.length) return _list.length; |
| 396 return _end; |
| 397 } |
| 398 |
| 399 Iterator<T> get iterator => |
| 400 new MappedListIterator<S, T>(_list, _f, _startIndex, _endIndex); |
| 401 |
| 402 void forEach(void action(T element)) { |
| 403 int length = _list.length; |
| 404 for (int i = _startIndex, n = _endIndex; i < n; i++) { |
| 405 action(_f(_list[i])); |
| 406 if (_list.length != length) { |
| 407 throw new ConcurrentModificationError(_list); |
| 408 } |
| 409 } |
| 410 } |
| 411 |
| 412 bool get isEmpty => _startIndex == _endIndex; |
| 413 |
| 414 int get length => _endIndex - _startIndex; |
| 415 |
| 416 T get first { |
| 417 int start = _startIndex; |
| 418 if (start == _endIndex) { |
| 419 throw new StateError("No elements"); |
| 420 } |
| 421 return _f(_list.elementAt(start)); |
| 422 } |
| 423 |
| 424 T get last { |
| 425 int end = _endIndex; |
| 426 if (end == _startIndex) { |
| 427 throw new StateError("No elements"); |
| 428 } |
| 429 return _f(_list.elementAt(end - 1)); |
| 430 } |
| 431 |
| 432 T get single { |
| 433 int start = _startIndex; |
| 434 int end = _endIndex; |
| 435 if (start != end - 1) { |
| 436 if (start == end) { |
| 437 throw new StateError("No elements"); |
| 438 } |
| 439 throw new StateError("Too many elements"); |
| 440 } |
| 441 return _f(_list[start]); |
| 442 } |
| 443 |
| 444 T elementAt(int index) { |
| 445 index += _startIndex; |
| 446 if (index >= _endIndex) { |
| 447 throw new StateError("No matching element"); |
| 448 } |
| 449 return _f(_list.elementAt(index)); |
| 450 } |
| 451 |
| 452 bool contains(T element) { |
| 453 int length = _list.length; |
| 454 for (int i = _startIndex, n = _endIndex; i < n; i++) { |
| 455 if (_f(_list[i]) == element) { |
| 456 return true; |
| 457 } |
| 458 if (_list.length != length) { |
| 459 throw new ConcurrentModificationError(_list); |
| 460 } |
| 461 } |
| 462 return false; |
| 463 } |
| 464 |
| 465 bool every(bool test(T element)) { |
| 466 int length = _list.length; |
| 467 for (int i = _startIndex, n = _endIndex; i < n; i++) { |
| 468 if (!test(_f(_list[i]))) return false; |
| 469 if (_list.length != length) { |
| 470 throw new ConcurrentModificationError(_list); |
| 471 } |
| 472 } |
| 473 return true; |
| 474 } |
| 475 |
| 476 bool any(bool test(T element)) { |
| 477 int length = _list.length; |
| 478 for (int i = _startIndex, n = _endIndex; i < n; i++) { |
| 479 if (test(_f(_list[i]))) return true; |
| 480 if (_list.length != length) { |
| 481 throw new ConcurrentModificationError(_list); |
| 482 } |
| 483 } |
| 484 return false; |
| 485 } |
| 486 |
| 487 T firstMatching(bool test(T element), { T orElse() }) { |
| 488 int length = _list.length; |
| 489 for (int i = _startIndex, n = _endIndex; i < n; i++) { |
| 490 T value = _f(_list[i]); |
| 491 if (test(value)) return value; |
| 492 if (_list.length != length) { |
| 493 throw new ConcurrentModificationError(_list); |
| 494 } |
| 495 } |
| 496 if (orElse != null) return orElse(); |
| 497 throw new StateError("No matching element"); |
| 498 } |
| 499 |
| 500 T lastMatching(bool test(T element), { T orElse() }) { |
| 501 int length = _list.length; |
| 502 for (int i = _endIndex - 1, start = _startIndex; i >= start; i++) { |
| 503 T value = _f(_list[i]); |
| 504 if (test(value)) return value; |
| 505 if (_list.length != length) { |
| 506 throw new ConcurrentModificationError(_list); |
| 507 } |
| 508 } |
| 509 if (orElse != null) return orElse(); |
| 510 throw new StateError("No matching element"); |
| 511 } |
| 512 |
| 513 T singleMatching(bool test(T element)) { |
| 514 int length = _list.length; |
| 515 T match; |
| 516 bool matchFound = false; |
| 517 for (int i = _startIndex, n = _endIndex; i < n; i++) { |
| 518 T value = _f(_list[i]); |
| 519 if (test(value)) { |
| 520 if (matchFound) { |
| 521 throw new StateError("More than one matching element"); |
| 522 } |
| 523 matchFound = true; |
| 524 match = value; |
| 525 } |
| 526 if (_list.length != length) { |
| 527 throw new ConcurrentModificationError(_list); |
| 528 } |
| 529 } |
| 530 if (matchFound) return match; |
| 531 throw new StateError("No matching element"); |
| 532 } |
| 533 |
| 534 T min([int compare(T a, T b)]) { |
| 535 if (compare == null) { |
| 536 var defaultCompare = Comparable.compare; |
| 537 compare = defaultCompare; |
| 538 } |
| 539 int length = _list.length; |
| 540 int start = _startIndex; |
| 541 int end = _endIndex; |
| 542 if (start == end) return null; |
| 543 T value = _f(_list[start]); |
| 544 if (_list.length != length) { |
| 545 throw new ConcurrentModificationError(_list); |
| 546 } |
| 547 for (int i = start + 1; i < end; i++) { |
| 548 T nextValue = _f(_list[i]); |
| 549 if (compare(value, nextValue) > 0) { |
| 550 value = nextValue; |
| 551 } |
| 552 if (_list.length != length) { |
| 553 throw new ConcurrentModificationError(_list); |
| 554 } |
| 555 } |
| 556 return value; |
| 557 } |
| 558 |
| 559 T max([int compare(T a, T b)]) { |
| 560 if (compare == null) { |
| 561 var defaultCompare = Comparable.compare; |
| 562 compare = defaultCompare; |
| 563 } |
| 564 int length = _list.length; |
| 565 int start = _startIndex; |
| 566 int end = _endIndex; |
| 567 if (start == end) return null; |
| 568 T value = _f(_list[start]); |
| 569 if (_list.length != length) { |
| 570 throw new ConcurrentModificationError(_list); |
| 571 } |
| 572 for (int i = start + 1; i < end; i++) { |
| 573 T nextValue = _f(_list[i]); |
| 574 if (compare(value, nextValue) < 0) { |
| 575 value = nextValue; |
| 576 } |
| 577 if (_list.length != length) { |
| 578 throw new ConcurrentModificationError(_list); |
| 579 } |
| 580 } |
| 581 return value; |
| 582 } |
| 583 |
| 584 String join([String separator]) { |
| 585 int start = _startIndex; |
| 586 int end = _endIndex; |
| 587 if (start == end) return ""; |
| 588 StringBuffer buffer = new StringBuffer("${_f(_list[start])}"); |
| 589 if (_list.length != length) { |
| 590 throw new ConcurrentModificationError(_list); |
| 591 } |
| 592 for (int i = start + 1; i < end; i++) { |
| 593 if (separator != null && separator != "") { |
| 594 buffer.add(separator); |
| 595 } |
| 596 buffer.add("${_f(_list[i])}"); |
| 597 if (_list.length != length) { |
| 598 throw new ConcurrentModificationError(_list); |
| 599 } |
| 600 } |
| 601 return buffer.toString(); |
| 602 } |
| 603 |
| 604 Iterable<T> where(bool test(T element)) => super.where(test); |
| 605 |
| 606 Iterable map(f(T element)) { |
| 607 return new MappedListIterable(_list, (S v) => f(_f(v)), _start, _end); |
| 608 } |
| 609 |
| 610 Iterable mappedBy(f(T element)) => map(f); |
| 611 |
| 612 reduce(var initialValue, combine(var previousValue, T element)) { |
| 613 return _list.reduce(initialValue, (v, S e) => combine(v, _f(e))); |
| 614 } |
| 615 |
| 616 Iterable<T> skip(int count) { |
| 617 int start = _startIndex + count; |
| 618 if (_end != null && start >= _end) { |
| 619 return new EmptyIterable<T>(); |
| 620 } |
| 621 return new MappedListIterable(_list, _f, start, _end); |
| 622 } |
| 623 |
| 624 Iterable<T> skipWhile(bool test(T element)) => super.skipWhile(test); |
| 625 |
| 626 Iterable<T> take(int count) { |
| 627 int newEnd = _start + count; |
| 628 if (_end == null || newEnd < _end) { |
| 629 return new MappedListIterable(_list, _f, _start, newEnd); |
| 630 } |
| 631 // Equivalent to "this". |
| 632 return new MappedListIterable(_list, _f, _start, _end); |
| 633 } |
| 634 |
| 635 Iterable<T> takeWhile(bool test(T element)) => super.takeWhile(test); |
| 636 |
| 637 List<T> toList() { |
| 638 List<T> result = new List<T>(); |
| 639 forEach(result.add); |
| 640 return result; |
| 641 } |
| 642 |
| 643 Set<T> toSet() { |
| 644 Set<T> result = new Set<T>(); |
| 645 forEach(result.add); |
| 646 return result; |
| 647 } |
| 378 } | 648 } |
| 379 | 649 |
| 650 /** |
| 651 * Iterator for [MappedListIterable]. |
| 652 * |
| 653 * A list iterator that iterates over (a sublist of) a list and |
| 654 * returns the values transformed by a function. |
| 655 * |
| 656 * As a list iterator, it throws if the length of the list has |
| 657 * changed during iteration. |
| 658 */ |
| 659 class MappedListIterator<S, T> implements Iterator<T> { |
| 660 List<S> _list; |
| 661 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 662 // checked mode. http://dartbug.com/7733 |
| 663 final /* _Transformation<S, T> */ _f; |
| 664 final int _endIndex; |
| 665 final int _length; |
| 666 int _index; |
| 667 T _current; |
| 668 |
| 669 MappedListIterator(List<S> list, this._f, int start, this._endIndex) |
| 670 : _list = list, _length = list.length, _index = start; |
| 671 |
| 672 T get current => _current; |
| 673 |
| 674 bool moveNext() { |
| 675 if (_list.length != _length) { |
| 676 throw new ConcurrentModificationError(_list); |
| 677 } |
| 678 if (_index >= _endIndex) { |
| 679 _current = null; |
| 680 return false; |
| 681 } |
| 682 _current = _f(_list[_index]); |
| 683 _index++; |
| 684 return true; |
| 685 } |
| 686 } |
| 687 |
| 380 typedef bool _ElementPredicate<E>(E element); | 688 typedef bool _ElementPredicate<E>(E element); |
| 381 | 689 |
| 382 class WhereIterable<E> extends Iterable<E> { | 690 class WhereIterable<E> extends Iterable<E> { |
| 383 final Iterable<E> _iterable; | 691 final Iterable<E> _iterable; |
| 384 // TODO(ahe): Restore type when feature is implemented in dart2js | 692 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 385 // checked mode. http://dartbug.com/7733 | 693 // checked mode. http://dartbug.com/7733 |
| 386 final /* _ElementPredicate */ _f; | 694 final /* _ElementPredicate */ _f; |
| 387 | 695 |
| 388 WhereIterable(this._iterable, bool this._f(E element)); | 696 WhereIterable(this._iterable, bool this._f(E element)); |
| 389 | 697 |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 E min([int compare(E a, E b)]) => null; | 962 E min([int compare(E a, E b)]) => null; |
| 655 | 963 |
| 656 E max([int compare(E a, E b)]) => null; | 964 E max([int compare(E a, E b)]) => null; |
| 657 | 965 |
| 658 String join([String separator]) => ""; | 966 String join([String separator]) => ""; |
| 659 | 967 |
| 660 Iterable<E> where(bool test(E element)) => this; | 968 Iterable<E> where(bool test(E element)) => this; |
| 661 | 969 |
| 662 Iterable map(f(E element)) => const EmptyIterable(); | 970 Iterable map(f(E element)) => const EmptyIterable(); |
| 663 | 971 |
| 972 Iterable mappedBy(f(E element)) => const EmptyIterable(); |
| 973 |
| 664 reduce(var initialValue, combine(var previousValue, E element)) { | 974 reduce(var initialValue, combine(var previousValue, E element)) { |
| 665 return initialValue; | 975 return initialValue; |
| 666 } | 976 } |
| 667 | 977 |
| 668 Iterable<E> skip(int count) => this; | 978 Iterable<E> skip(int count) => this; |
| 669 | 979 |
| 670 Iterable<E> skipWhile(bool test(E element)) => this; | 980 Iterable<E> skipWhile(bool test(E element)) => this; |
| 671 | 981 |
| 672 Iterable<E> take(int count) => this; | 982 Iterable<E> take(int count) => this; |
| 673 | 983 |
| 674 Iterable<E> takeWhile(bool test(E element)) => this; | 984 Iterable<E> takeWhile(bool test(E element)) => this; |
| 675 | 985 |
| 676 List toList() => <E>[]; | 986 List toList() => <E>[]; |
| 677 | 987 |
| 678 Set toSet() => new Set<E>(); | 988 Set toSet() => new Set<E>(); |
| 679 } | 989 } |
| 680 | 990 |
| 681 /** The always empty iterator. */ | 991 /** The always empty iterator. */ |
| 682 class EmptyIterator<E> implements Iterator<E> { | 992 class EmptyIterator<E> implements Iterator<E> { |
| 683 const EmptyIterator(); | 993 const EmptyIterator(); |
| 684 bool moveNext() => false; | 994 bool moveNext() => false; |
| 685 E get current => null; | 995 E get current => null; |
| 686 } | 996 } |
| 687 | 997 |
| 688 /** An [Iterator] that can move in both directions. */ | 998 /** An [Iterator] that can move in both directions. */ |
| 689 abstract class BiDirectionalIterator<T> implements Iterator<T> { | 999 abstract class BiDirectionalIterator<T> implements Iterator<T> { |
| 690 bool movePrevious(); | 1000 bool movePrevious(); |
| 691 } | 1001 } |
| OLD | NEW |