| // Copyright 2014 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| part of quiver.iterables; |
| |
| Iterable generate(initial(), next(o)) => new GeneratingIterable(initial, next); |
| |
| /// An Iterable who's first value is [object] and who's subsequent values are |
| /// generated by passing the current value to the [next] function. |
| /// |
| /// The class is useful for creating lazy iterables from object hierarchies and |
| /// graphs. |
| /// |
| /// It's important that for the given initial value and next function that the |
| /// sequence of items eventually terminates. Otherwise calling methods that |
| /// expect a finite sequence, like `length` or `last`, will cause an infinite |
| /// loop. |
| /// |
| /// Example: |
| /// |
| /// class Node { |
| /// Node parent; |
| /// |
| /// /// An iterable of node and all ancestors up to the root. |
| /// Iterable<Node> ancestors = |
| /// new GeneratingIterable<Node>(() => this, (n) => n.parent); |
| /// |
| /// /// An iterable of the root and the path of nodes to this. The |
| /// /// reverse of ancestors. |
| /// Iterable<Node> path = ancestors.toList().reversed(); |
| /// } |
| /// |
| class GeneratingIterable<T> extends IterableBase<T> { |
| final initial; |
| final next; |
| |
| GeneratingIterable(T this.initial(), T this.next(T o)); |
| |
| @override |
| Iterator<T> get iterator => new _GeneratingIterator(initial(), next); |
| } |
| |
| class _GeneratingIterator<T> implements Iterator<T> { |
| final next; |
| T object; |
| bool started = false; |
| |
| _GeneratingIterator(T this.object, T this.next(T o)); |
| |
| @override |
| T get current => started ? object : null; |
| |
| @override |
| bool moveNext() { |
| if (object == null) return false; |
| if (started) { |
| object = next(object); |
| } else { |
| started = true; |
| } |
| return object != null; |
| } |
| } |