OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.core; | 5 part of dart.core; |
6 | 6 |
7 /** | 7 /** |
8 * An object that uses an [Iterator] to serve objects one at a time. | 8 * An object that uses an [Iterator] to serve objects one at a time. |
9 * | 9 * |
10 * You can iterate over all objects served by an Iterable object | 10 * You can iterate over all objects served by an Iterable object |
(...skipping 23 matching lines...) Expand all Loading... |
34 abstract class Iterable<E> { | 34 abstract class Iterable<E> { |
35 const Iterable(); | 35 const Iterable(); |
36 | 36 |
37 /** | 37 /** |
38 * Creates an Iterable that generates its elements dynamically. | 38 * Creates an Iterable that generates its elements dynamically. |
39 * | 39 * |
40 * The Iterators created by the Iterable count from | 40 * The Iterators created by the Iterable count from |
41 * zero to [:count - 1:] while iterating, and call [generator] | 41 * zero to [:count - 1:] while iterating, and call [generator] |
42 * with that index to create the next value. | 42 * with that index to create the next value. |
43 * | 43 * |
| 44 * If [generator] is omitted, it defaults to an identity function |
| 45 * on integers `(int x) => x`, so it should only be omitted if the type |
| 46 * parameter allows integer values. |
| 47 * |
44 * As an Iterable, [:new Iterable.generate(n, generator)):] is equivalent to | 48 * As an Iterable, [:new Iterable.generate(n, generator)):] is equivalent to |
45 * [:const [0, ..., n - 1].map(generator):] | 49 * [:const [0, ..., n - 1].map(generator):] |
46 */ | 50 */ |
47 factory Iterable.generate(int count, E generator(int index)) { | 51 factory Iterable.generate(int count, [E generator(int index)]) { |
| 52 if (count <= 0) return new EmptyIterable<E>(); |
48 return new _GeneratorIterable<E>(count, generator); | 53 return new _GeneratorIterable<E>(count, generator); |
49 } | 54 } |
50 | 55 |
51 /** | 56 /** |
52 * Returns an Iterator that iterates over this Iterable object. | 57 * Returns an Iterator that iterates over this Iterable object. |
53 */ | 58 */ |
54 Iterator<E> get iterator; | 59 Iterator<E> get iterator; |
55 | 60 |
56 /** | 61 /** |
57 * Returns a lazy [Iterable] where each element [:e:] of `this` is replaced | 62 * Returns a lazy [Iterable] where each element [:e:] of `this` is replaced |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 * function may simply return any element without any iteration if there are | 287 * function may simply return any element without any iteration if there are |
283 * at least [index] elements in `this`. | 288 * at least [index] elements in `this`. |
284 */ | 289 */ |
285 E elementAt(int index); | 290 E elementAt(int index); |
286 } | 291 } |
287 | 292 |
288 typedef E _Generator<E>(int index); | 293 typedef E _Generator<E>(int index); |
289 | 294 |
290 class _GeneratorIterable<E> extends IterableBase<E> | 295 class _GeneratorIterable<E> extends IterableBase<E> |
291 implements EfficientLength { | 296 implements EfficientLength { |
292 final int _count; | 297 final int _start; |
| 298 final int _end; |
293 final _Generator<E> _generator; | 299 final _Generator<E> _generator; |
294 _GeneratorIterable(this._count, this._generator); | 300 _GeneratorIterable(this._end, E generator(int n)) |
295 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); | 301 : _start = 0, |
296 int get length => _count; | 302 _generator = (generator != null) ? generator : _id; |
| 303 |
| 304 _GeneratorIterable.slice(this._start, this._end, this._generator); |
| 305 |
| 306 Iterator<E> get iterator => |
| 307 new _GeneratorIterator<E>(_start, _end, _generator); |
| 308 int get length => _end - _start; |
| 309 |
| 310 Iterable<E> skip(int n) { |
| 311 if (n < 0) throw new RangeError.value(n); |
| 312 if (n == 0) return this; |
| 313 int newStart = _start + n; |
| 314 if (newStart >= _end) return new EmptyIterable<E>(); |
| 315 return new _GeneratorIterable<E>.slice(newStart, _end, _generator); |
| 316 } |
| 317 |
| 318 Iterable<E> take(int n) { |
| 319 if (n < 0) throw new RangeError.value(n); |
| 320 if (n == 0) return new EmptyIterable<E>(); |
| 321 int newEnd = _start + n; |
| 322 if (newEnd >= _end) return this; |
| 323 return new _GeneratorIterable<E>.slice(_start, newEnd, _generator); |
| 324 } |
| 325 |
| 326 static int _id(int n) => n; |
297 } | 327 } |
298 | 328 |
299 class _GeneratorIterator<E> implements Iterator<E> { | 329 class _GeneratorIterator<E> implements Iterator<E> { |
300 final int _count; | 330 final int _end; |
301 final _Generator<E> _generator; | 331 final _Generator<E> _generator; |
302 int _index = 0; | 332 int _index; |
303 E _current; | 333 E _current; |
304 | 334 |
305 _GeneratorIterator(this._count, this._generator); | 335 _GeneratorIterator(this._index, this._end, this._generator); |
306 | 336 |
307 bool moveNext() { | 337 bool moveNext() { |
308 if (_index < _count) { | 338 if (_index < _end) { |
309 _current = _generator(_index); | 339 _current = _generator(_index); |
310 _index++; | 340 _index++; |
311 return true; | 341 return true; |
312 } else { | 342 } else { |
313 _current = null; | 343 _current = null; |
314 return false; | 344 return false; |
315 } | 345 } |
316 } | 346 } |
317 | 347 |
318 E get current => _current; | 348 E get current => _current; |
319 } | 349 } |
320 | 350 |
321 /** | 351 /** |
322 * An Iterator that allows moving backwards as well as forwards. | 352 * An Iterator that allows moving backwards as well as forwards. |
323 */ | 353 */ |
324 abstract class BidirectionalIterator<E> implements Iterator<E> { | 354 abstract class BidirectionalIterator<E> implements Iterator<E> { |
325 /** | 355 /** |
326 * Move back to the previous element. | 356 * Move back to the previous element. |
327 * | 357 * |
328 * Returns true and updates [current] if successful. Returns false | 358 * Returns true and updates [current] if successful. Returns false |
329 * and sets [current] to null if there is no previous element. | 359 * and sets [current] to null if there is no previous element. |
330 */ | 360 */ |
331 bool movePrevious(); | 361 bool movePrevious(); |
332 } | 362 } |
OLD | NEW |