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

Side by Side Diff: sdk/lib/core/iterable.dart

Issue 14022007: Move Iterable implementation to collection. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Merge to head. Created 7 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « sdk/lib/collection/splay_tree.dart ('k') | sdk/lib/core/set.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 * The [Iterable] interface allows to get an [Iterator] out of an 8 * The [Iterable] interface allows to get an [Iterator] out of an
9 * [Iterable] object. 9 * [Iterable] object.
10 * 10 *
(...skipping 30 matching lines...) Expand all
41 /** 41 /**
42 * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced 42 * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced
43 * by the result of [:f(e):]. 43 * by the result of [:f(e):].
44 * 44 *
45 * This method returns a view of the mapped elements. As long as the 45 * This method returns a view of the mapped elements. As long as the
46 * returned [Iterable] is not iterated over, the supplied function [f] will 46 * returned [Iterable] is not iterated over, the supplied function [f] will
47 * not be invoked. The transformed elements will not be cached. Iterating 47 * not be invoked. The transformed elements will not be cached. Iterating
48 * multiple times over the the returned [Iterable] will invoke the supplied 48 * multiple times over the the returned [Iterable] will invoke the supplied
49 * function [f] multiple times on the same element. 49 * function [f] multiple times on the same element.
50 */ 50 */
51 Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); 51 Iterable map(f(E element));
52 52
53 /** 53 /**
54 * Returns a lazy [Iterable] with all elements that satisfy the 54 * Returns a lazy [Iterable] with all elements that satisfy the
55 * predicate [f]. 55 * predicate [f].
56 * 56 *
57 * This method returns a view of the mapped elements. As long as the 57 * This method returns a view of the mapped elements. As long as the
58 * returned [Iterable] is not iterated over, the supplied function [f] will 58 * returned [Iterable] is not iterated over, the supplied function [f] will
59 * not be invoked. Iterating will not cache results, and thus iterating 59 * not be invoked. Iterating will not cache results, and thus iterating
60 * multiple times over the the returned [Iterable] will invoke the supplied 60 * multiple times over the the returned [Iterable] will invoke the supplied
61 * function [f] multiple times on the same element. 61 * function [f] multiple times on the same element.
62 */ 62 */
63 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); 63 Iterable<E> where(bool f(E element));
64
65 64
66 /** 65 /**
67 * Expand each element of this [Iterable] into zero or more elements. 66 * Expand each element of this [Iterable] into zero or more elements.
68 * 67 *
69 * The resulting Iterable will run through the elements returned 68 * The resulting Iterable will run through the elements returned
70 * by [f] for each element of this, in order. 69 * by [f] for each element of this, in order.
71 * 70 *
72 * The returned [Iterable] is lazy, and will call [f] for each element 71 * The returned [Iterable] is lazy, and will call [f] for each element
73 * of this every time it's iterated. 72 * of this every time it's iterated.
74 */ 73 */
75 Iterable expand(Iterable f(E element)) => 74 Iterable expand(Iterable f(E element));
76 new ExpandIterable<E, dynamic>(this, f);
77 75
78 /** 76 /**
79 * Check whether the collection contains an element equal to [element]. 77 * Check whether the collection contains an element equal to [element].
80 */ 78 */
81 bool contains(E element) { 79 bool contains(E element);
82 for (E e in this) {
83 if (e == element) return true;
84 }
85 return false;
86 }
87 80
88 /** 81 /**
89 * Applies the function [f] to each element of this collection. 82 * Applies the function [f] to each element of this collection.
90 */ 83 */
91 void forEach(void f(E element)) { 84 void forEach(void f(E element));
92 for (E element in this) f(element);
93 }
94 85
95 /** 86 /**
96 * Reduce a collection to a single value by iteratively combining elements 87 * Reduces a collection to a single value by iteratively combining elements
97 * of the collection using the provided function. 88 * of the collection using the provided function.
98 * 89 *
99 * Example of calculating the sum of an iterable: 90 * Example of calculating the sum of an iterable:
100 * 91 *
101 * iterable.reduce((value, element) => value + element); 92 * iterable.reduce((value, element) => value + element);
102 * 93 *
103 */ 94 */
104 E reduce(E combine(E value, E element)) { 95 E reduce(E combine(E value, E element));
105 Iterator<E> iterator = this.iterator;
106 if (!iterator.moveNext()) {
107 throw new StateError("No elements");
108 }
109 E value = iterator.current;
110 while (iterator.moveNext()) {
111 value = combine(value, iterator.current);
112 }
113 return value;
114 }
115 96
116 /** 97 /**
117 * Reduce a collection to a single value by iteratively combining each element 98 * Reduces a collection to a single value by iteratively combining each
118 * of the collection with an existing value using the provided function. 99 * element of the collection with an existing value using the provided
100 * function.
101 *
119 * Use [initialValue] as the initial value, and the function [combine] to 102 * Use [initialValue] as the initial value, and the function [combine] to
120 * create a new value from the previous one and an element. 103 * create a new value from the previous one and an element.
121 * 104 *
122 * Example of calculating the sum of an iterable: 105 * Example of calculating the sum of an iterable:
123 * 106 *
124 * iterable.fold(0, (prev, element) => prev + element); 107 * iterable.fold(0, (prev, element) => prev + element);
125 * 108 *
126 */ 109 */
127 dynamic fold(var initialValue, 110 dynamic fold(var initialValue,
128 dynamic combine(var previousValue, E element)) { 111 dynamic combine(var previousValue, E element));
129 var value = initialValue;
130 for (E element in this) value = combine(value, element);
131 return value;
132 }
133 112
134 /** 113 /**
135 * Returns true if every elements of this collection satisify the 114 * Returns true if every elements of this collection satisify the
136 * predicate [f]. Returns false otherwise. 115 * predicate [f]. Returns false otherwise.
137 */ 116 */
138 bool every(bool f(E element)) { 117 bool every(bool f(E element));
139 for (E element in this) {
140 if (!f(element)) return false;
141 }
142 return true;
143 }
144 118
145 /** 119 /**
146 * Convert each element to a [String] and concatenate the strings. 120 * Converts each element to a [String] and concatenates the strings.
147 * 121 *
148 * Converts each element to a [String] by calling [Object.toString] on it. 122 * Converts each element to a [String] by calling [Object.toString] on it.
149 * Then concatenates the strings, optionally separated by the [separator] 123 * Then concatenates the strings, optionally separated by the [separator]
150 * string. 124 * string.
151 */ 125 */
152 String join([String separator = ""]) { 126 String join([String separator = ""]) {
153 StringBuffer buffer = new StringBuffer(); 127 StringBuffer buffer = new StringBuffer();
154 buffer.writeAll(this, separator); 128 buffer.writeAll(this, separator);
155 return buffer.toString(); 129 return buffer.toString();
156 } 130 }
157 131
158 /** 132 /**
159 * Returns true if one element of this collection satisfies the 133 * Returns true if one element of this collection satisfies the
160 * predicate [f]. Returns false otherwise. 134 * predicate [f]. Returns false otherwise.
161 */ 135 */
162 bool any(bool f(E element)) { 136 bool any(bool f(E element));
163 for (E element in this) {
164 if (f(element)) return true;
165 }
166 return false;
167 }
168 137
169 List<E> toList({ bool growable: true }) => 138 /**
170 new List<E>.from(this, growable: growable); 139 * Creates a [List] containing the elements of this [Iterable].
171 Set<E> toSet() => new Set<E>.from(this); 140 *
141 * The elements will be in iteration order. The list is fixed-length
142 * if [growable] is false.
143 */
144 List<E> toList({ bool growable: true });
145
146 /**
147 * Creates a [Set] containing the elements of this [Iterable].
148 */
149 Set<E> toSet();
172 150
173 /** 151 /**
174 * Returns the number of elements in [this]. 152 * Returns the number of elements in [this].
175 * 153 *
176 * Counting all elements may be involve running through all elements and can 154 * Counting all elements may be involve running through all elements and can
177 * therefore be slow. 155 * therefore be slow.
178 */ 156 */
179 int get length { 157 int get length;
180 int count = 0;
181 Iterator it = iterator;
182 while (it.moveNext()) {
183 count++;
184 }
185 return count;
186 }
187 158
188 /** 159 /**
189 * Returns true if there is no element in this collection. 160 * Returns true if there is no element in this collection.
190 */ 161 */
191 bool get isEmpty => !iterator.moveNext(); 162 bool get isEmpty;
192 163
193 /** 164 /**
194 * Returns an [Iterable] with at most [n] elements. 165 * Returns an [Iterable] with at most [n] elements.
195 * 166 *
196 * The returned [Iterable] may contain fewer than [n] elements, if [this] 167 * The returned [Iterable] may contain fewer than [n] elements, if [this]
197 * contains fewer than [n] elements. 168 * contains fewer than [n] elements.
198 */ 169 */
199 Iterable<E> take(int n) { 170 Iterable<E> take(int n);
200 return new TakeIterable<E>(this, n);
201 }
202 171
203 /** 172 /**
204 * Returns an [Iterable] that stops once [test] is not satisfied anymore. 173 * Returns an [Iterable] that stops once [test] is not satisfied anymore.
205 * 174 *
206 * The filtering happens lazily. Every new [Iterator] of the returned 175 * The filtering happens lazily. Every new [Iterator] of the returned
207 * [Iterable] will start iterating over the elements of [this]. 176 * [Iterable] will start iterating over the elements of [this].
208 * When the iterator encounters an element [:e:] that does not satisfy [test], 177 * When the iterator encounters an element [:e:] that does not satisfy [test],
209 * it discards [:e:] and moves into the finished state. That is, it will not 178 * it discards [:e:] and moves into the finished state. That is, it will not
210 * ask or provide any more elements. 179 * ask or provide any more elements.
211 */ 180 */
212 Iterable<E> takeWhile(bool test(E value)) { 181 Iterable<E> takeWhile(bool test(E value));
213 return new TakeWhileIterable<E>(this, test);
214 }
215 182
216 /** 183 /**
217 * Returns an [Iterable] that skips the first [n] elements. 184 * Returns an [Iterable] that skips the first [n] elements.
218 * 185 *
219 * If [this] has fewer than [n] elements, then the resulting [Iterable] will 186 * If [this] has fewer than [n] elements, then the resulting [Iterable] will
220 * be empty. 187 * be empty.
221 */ 188 */
222 Iterable<E> skip(int n) { 189 Iterable<E> skip(int n);
223 return new SkipIterable<E>(this, n);
224 }
225 190
226 /** 191 /**
227 * Returns an [Iterable] that skips elements while [test] is satisfied. 192 * Returns an [Iterable] that skips elements while [test] is satisfied.
228 * 193 *
229 * The filtering happens lazily. Every new [Iterator] of the returned 194 * The filtering happens lazily. Every new [Iterator] of the returned
230 * [Iterable] will iterate over all elements of [this]. 195 * [Iterable] will iterate over all elements of [this].
231 * As long as the iterator's elements do not satisfy [test] they are 196 * As long as the iterator's elements do not satisfy [test] they are
232 * discarded. Once an element satisfies the [test] the iterator stops testing 197 * discarded. Once an element satisfies the [test] the iterator stops testing
233 * and uses every element unconditionally. 198 * and uses every element unconditionally.
234 */ 199 */
235 Iterable<E> skipWhile(bool test(E value)) { 200 Iterable<E> skipWhile(bool test(E value));
236 return new SkipWhileIterable<E>(this, test);
237 }
238 201
239 /** 202 /**
240 * Returns the first element. 203 * Returns the first element.
241 * 204 *
242 * If [this] is empty throws a [StateError]. Otherwise this method is 205 * If [this] is empty throws a [StateError]. Otherwise this method is
243 * equivalent to [:this.elementAt(0):] 206 * equivalent to [:this.elementAt(0):]
244 */ 207 */
245 E get first { 208 E get first;
246 Iterator it = iterator;
247 if (!it.moveNext()) {
248 throw new StateError("No elements");
249 }
250 return it.current;
251 }
252 209
253 /** 210 /**
254 * Returns the last element. 211 * Returns the last element.
255 * 212 *
256 * If [this] is empty throws a [StateError]. 213 * If [this] is empty throws a [StateError].
257 */ 214 */
258 E get last { 215 E get last;
259 Iterator it = iterator;
260 if (!it.moveNext()) {
261 throw new StateError("No elements");
262 }
263 E result;
264 do {
265 result = it.current;
266 } while(it.moveNext());
267 return result;
268 }
269 216
270 /** 217 /**
271 * Returns the single element in [this]. 218 * Returns the single element in [this].
272 * 219 *
273 * If [this] is empty or has more than one element throws a [StateError]. 220 * If [this] is empty or has more than one element throws a [StateError].
274 */ 221 */
275 E get single { 222 E get single;
276 Iterator it = iterator;
277 if (!it.moveNext()) throw new StateError("No elements");
278 E result = it.current;
279 if (it.moveNext()) throw new StateError("More than one element");
280 return result;
281 }
282 223
283 /** 224 /**
284 * Returns the first element that satisfies the given predicate [f]. 225 * Returns the first element that satisfies the given predicate [f].
285 * 226 *
286 * If none matches, the result of invoking the [orElse] function is 227 * If none matches, the result of invoking the [orElse] function is
287 * returned. By default, when [orElse] is `null`, a [StateError] is 228 * returned. By default, when [orElse] is `null`, a [StateError] is
288 * thrown. 229 * thrown.
289 */ 230 */
290 E firstWhere(bool test(E value), { E orElse() }) { 231 E firstWhere(bool test(E value), { E orElse() });
291 // TODO(floitsch): check that arguments are of correct type?
292 for (E element in this) {
293 if (test(element)) return element;
294 }
295 if (orElse != null) return orElse();
296 throw new StateError("No matching element");
297 }
298 232
299 /** 233 /**
300 * Returns the last element that satisfies the given predicate [f]. 234 * Returns the last element that satisfies the given predicate [f].
301 * 235 *
302 * If none matches, the result of invoking the [orElse] function is 236 * If none matches, the result of invoking the [orElse] function is
303 * returned. By default, when [orElse] is [:null:], a [StateError] is 237 * returned. By default, when [orElse] is [:null:], a [StateError] is
304 * thrown. 238 * thrown.
305 */ 239 */
306 E lastWhere(bool test(E value), {E orElse()}) { 240 E lastWhere(bool test(E value), {E orElse()});
307 // TODO(floitsch): check that arguments are of correct type?
308 E result = null;
309 bool foundMatching = false;
310 for (E element in this) {
311 if (test(element)) {
312 result = element;
313 foundMatching = true;
314 }
315 }
316 if (foundMatching) return result;
317 if (orElse != null) return orElse();
318 throw new StateError("No matching element");
319 }
320 241
321 /** 242 /**
322 * Returns the single element that satisfies [f]. If no or more than one 243 * Returns the single element that satisfies [f]. If no or more than one
323 * element match then a [StateError] is thrown. 244 * element match then a [StateError] is thrown.
324 */ 245 */
325 E singleWhere(bool test(E value)) { 246 E singleWhere(bool test(E value));
326 // TODO(floitsch): check that argument is of correct type?
327 E result = null;
328 bool foundMatching = false;
329 for (E element in this) {
330 if (test(element)) {
331 if (foundMatching) {
332 throw new StateError("More than one matching element");
333 }
334 result = element;
335 foundMatching = true;
336 }
337 }
338 if (foundMatching) return result;
339 throw new StateError("No matching element");
340 }
341 247
342 /** 248 /**
343 * Returns the [index]th element. 249 * Returns the [index]th element.
344 * 250 *
345 * If [this] [Iterable] has fewer than [index] elements throws a 251 * If [this] [Iterable] has fewer than [index] elements throws a
346 * [RangeError]. 252 * [RangeError].
347 * 253 *
348 * Note: if [this] does not have a deterministic iteration order then the 254 * Note: if [this] does not have a deterministic iteration order then the
349 * function may simply return any element without any iteration if there are 255 * function may simply return any element without any iteration if there are
350 * at least [index] elements in [this]. 256 * at least [index] elements in [this].
351 */ 257 */
352 E elementAt(int index) { 258 E elementAt(int index);
353 if (index is! int || index < 0) throw new RangeError.value(index);
354 int remaining = index;
355 for (E element in this) {
356 if (remaining == 0) return element;
357 remaining--;
358 }
359 throw new RangeError.value(index);
360 }
361 } 259 }
362 260
363 261
364 typedef E _Generator<E>(int index); 262 typedef E _Generator<E>(int index);
365 263
366 class _GeneratorIterable<E> extends Iterable<E> { 264 class _GeneratorIterable<E> extends IterableBase<E> {
367 final int _count; 265 final int _count;
368 final _Generator<E> _generator; 266 final _Generator<E> _generator;
369 _GeneratorIterable(this._count, this._generator); 267 _GeneratorIterable(this._count, this._generator);
370 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); 268 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator);
371 } 269 }
372 270
373 class _GeneratorIterator<E> implements Iterator<E> { 271 class _GeneratorIterator<E> implements Iterator<E> {
374 final int _count; 272 final int _count;
375 final _Generator<E> _generator; 273 final _Generator<E> _generator;
376 int _index = 0; 274 int _index = 0;
(...skipping 11 matching lines...) Expand all
388 return false; 286 return false;
389 } 287 }
390 } 288 }
391 289
392 E get current => _current; 290 E get current => _current;
393 } 291 }
394 292
395 /** 293 /**
396 * An [Iterator] that allows moving backwards as well as forwards. 294 * An [Iterator] that allows moving backwards as well as forwards.
397 */ 295 */
398 abstract class BidirectionalIterator<T> extends Iterator<T> { 296 abstract class BidirectionalIterator<E> implements Iterator<E> {
399 /** 297 /**
400 * Move back to the previous element. 298 * Move back to the previous element.
401 * 299 *
402 * Returns true and updates [current] if successful. Returns false 300 * Returns true and updates [current] if successful. Returns false
403 * and sets [current] to null if there is no previous element. 301 * and sets [current] to null if there is no previous element.
404 */ 302 */
405 bool movePrevious(); 303 bool movePrevious();
406 } 304 }
OLDNEW
« no previous file with comments | « sdk/lib/collection/splay_tree.dart ('k') | sdk/lib/core/set.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698