|
1 /*** |
|
2 |
|
3 MochiKit.Iter 1.4.2 |
|
4 |
|
5 See <http://mochikit.com/> for documentation, downloads, license, etc. |
|
6 |
|
7 (c) 2005 Bob Ippolito. All rights Reserved. |
|
8 |
|
9 ***/ |
|
10 |
|
11 MochiKit.Base._deps('Iter', ['Base']); |
|
12 |
|
13 MochiKit.Iter.NAME = "MochiKit.Iter"; |
|
14 MochiKit.Iter.VERSION = "1.4.2"; |
|
15 MochiKit.Base.update(MochiKit.Iter, { |
|
16 __repr__: function () { |
|
17 return "[" + this.NAME + " " + this.VERSION + "]"; |
|
18 }, |
|
19 toString: function () { |
|
20 return this.__repr__(); |
|
21 }, |
|
22 |
|
23 /** @id MochiKit.Iter.registerIteratorFactory */ |
|
24 registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) { |
|
25 MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override); |
|
26 }, |
|
27 |
|
28 /** @id MochiKit.Iter.isIterable */ |
|
29 isIterable: function(o) { |
|
30 return o != null && |
|
31 (typeof(o.next) == "function" || typeof(o.iter) == "function"); |
|
32 }, |
|
33 |
|
34 /** @id MochiKit.Iter.iter */ |
|
35 iter: function (iterable, /* optional */ sentinel) { |
|
36 var self = MochiKit.Iter; |
|
37 if (arguments.length == 2) { |
|
38 return self.takewhile( |
|
39 function (a) { return a != sentinel; }, |
|
40 iterable |
|
41 ); |
|
42 } |
|
43 if (typeof(iterable.next) == 'function') { |
|
44 return iterable; |
|
45 } else if (typeof(iterable.iter) == 'function') { |
|
46 return iterable.iter(); |
|
47 /* |
|
48 } else if (typeof(iterable.__iterator__) == 'function') { |
|
49 // |
|
50 // XXX: We can't support JavaScript 1.7 __iterator__ directly |
|
51 // because of Object.prototype.__iterator__ |
|
52 // |
|
53 return iterable.__iterator__(); |
|
54 */ |
|
55 } |
|
56 |
|
57 try { |
|
58 return self.iteratorRegistry.match(iterable); |
|
59 } catch (e) { |
|
60 var m = MochiKit.Base; |
|
61 if (e == m.NotFound) { |
|
62 e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable"); |
|
63 } |
|
64 throw e; |
|
65 } |
|
66 }, |
|
67 |
|
68 /** @id MochiKit.Iter.count */ |
|
69 count: function (n) { |
|
70 if (!n) { |
|
71 n = 0; |
|
72 } |
|
73 var m = MochiKit.Base; |
|
74 return { |
|
75 repr: function () { return "count(" + n + ")"; }, |
|
76 toString: m.forwardCall("repr"), |
|
77 next: m.counter(n) |
|
78 }; |
|
79 }, |
|
80 |
|
81 /** @id MochiKit.Iter.cycle */ |
|
82 cycle: function (p) { |
|
83 var self = MochiKit.Iter; |
|
84 var m = MochiKit.Base; |
|
85 var lst = []; |
|
86 var iterator = self.iter(p); |
|
87 return { |
|
88 repr: function () { return "cycle(...)"; }, |
|
89 toString: m.forwardCall("repr"), |
|
90 next: function () { |
|
91 try { |
|
92 var rval = iterator.next(); |
|
93 lst.push(rval); |
|
94 return rval; |
|
95 } catch (e) { |
|
96 if (e != self.StopIteration) { |
|
97 throw e; |
|
98 } |
|
99 if (lst.length === 0) { |
|
100 this.next = function () { |
|
101 throw self.StopIteration; |
|
102 }; |
|
103 } else { |
|
104 var i = -1; |
|
105 this.next = function () { |
|
106 i = (i + 1) % lst.length; |
|
107 return lst[i]; |
|
108 }; |
|
109 } |
|
110 return this.next(); |
|
111 } |
|
112 } |
|
113 }; |
|
114 }, |
|
115 |
|
116 /** @id MochiKit.Iter.repeat */ |
|
117 repeat: function (elem, /* optional */n) { |
|
118 var m = MochiKit.Base; |
|
119 if (typeof(n) == 'undefined') { |
|
120 return { |
|
121 repr: function () { |
|
122 return "repeat(" + m.repr(elem) + ")"; |
|
123 }, |
|
124 toString: m.forwardCall("repr"), |
|
125 next: function () { |
|
126 return elem; |
|
127 } |
|
128 }; |
|
129 } |
|
130 return { |
|
131 repr: function () { |
|
132 return "repeat(" + m.repr(elem) + ", " + n + ")"; |
|
133 }, |
|
134 toString: m.forwardCall("repr"), |
|
135 next: function () { |
|
136 if (n <= 0) { |
|
137 throw MochiKit.Iter.StopIteration; |
|
138 } |
|
139 n -= 1; |
|
140 return elem; |
|
141 } |
|
142 }; |
|
143 }, |
|
144 |
|
145 /** @id MochiKit.Iter.next */ |
|
146 next: function (iterator) { |
|
147 return iterator.next(); |
|
148 }, |
|
149 |
|
150 /** @id MochiKit.Iter.izip */ |
|
151 izip: function (p, q/*, ...*/) { |
|
152 var m = MochiKit.Base; |
|
153 var self = MochiKit.Iter; |
|
154 var next = self.next; |
|
155 var iterables = m.map(self.iter, arguments); |
|
156 return { |
|
157 repr: function () { return "izip(...)"; }, |
|
158 toString: m.forwardCall("repr"), |
|
159 next: function () { return m.map(next, iterables); } |
|
160 }; |
|
161 }, |
|
162 |
|
163 /** @id MochiKit.Iter.ifilter */ |
|
164 ifilter: function (pred, seq) { |
|
165 var m = MochiKit.Base; |
|
166 seq = MochiKit.Iter.iter(seq); |
|
167 if (pred === null) { |
|
168 pred = m.operator.truth; |
|
169 } |
|
170 return { |
|
171 repr: function () { return "ifilter(...)"; }, |
|
172 toString: m.forwardCall("repr"), |
|
173 next: function () { |
|
174 while (true) { |
|
175 var rval = seq.next(); |
|
176 if (pred(rval)) { |
|
177 return rval; |
|
178 } |
|
179 } |
|
180 // mozilla warnings aren't too bright |
|
181 return undefined; |
|
182 } |
|
183 }; |
|
184 }, |
|
185 |
|
186 /** @id MochiKit.Iter.ifilterfalse */ |
|
187 ifilterfalse: function (pred, seq) { |
|
188 var m = MochiKit.Base; |
|
189 seq = MochiKit.Iter.iter(seq); |
|
190 if (pred === null) { |
|
191 pred = m.operator.truth; |
|
192 } |
|
193 return { |
|
194 repr: function () { return "ifilterfalse(...)"; }, |
|
195 toString: m.forwardCall("repr"), |
|
196 next: function () { |
|
197 while (true) { |
|
198 var rval = seq.next(); |
|
199 if (!pred(rval)) { |
|
200 return rval; |
|
201 } |
|
202 } |
|
203 // mozilla warnings aren't too bright |
|
204 return undefined; |
|
205 } |
|
206 }; |
|
207 }, |
|
208 |
|
209 /** @id MochiKit.Iter.islice */ |
|
210 islice: function (seq/*, [start,] stop[, step] */) { |
|
211 var self = MochiKit.Iter; |
|
212 var m = MochiKit.Base; |
|
213 seq = self.iter(seq); |
|
214 var start = 0; |
|
215 var stop = 0; |
|
216 var step = 1; |
|
217 var i = -1; |
|
218 if (arguments.length == 2) { |
|
219 stop = arguments[1]; |
|
220 } else if (arguments.length == 3) { |
|
221 start = arguments[1]; |
|
222 stop = arguments[2]; |
|
223 } else { |
|
224 start = arguments[1]; |
|
225 stop = arguments[2]; |
|
226 step = arguments[3]; |
|
227 } |
|
228 return { |
|
229 repr: function () { |
|
230 return "islice(" + ["...", start, stop, step].join(", ") + ")"; |
|
231 }, |
|
232 toString: m.forwardCall("repr"), |
|
233 next: function () { |
|
234 var rval; |
|
235 while (i < start) { |
|
236 rval = seq.next(); |
|
237 i++; |
|
238 } |
|
239 if (start >= stop) { |
|
240 throw self.StopIteration; |
|
241 } |
|
242 start += step; |
|
243 return rval; |
|
244 } |
|
245 }; |
|
246 }, |
|
247 |
|
248 /** @id MochiKit.Iter.imap */ |
|
249 imap: function (fun, p, q/*, ...*/) { |
|
250 var m = MochiKit.Base; |
|
251 var self = MochiKit.Iter; |
|
252 var iterables = m.map(self.iter, m.extend(null, arguments, 1)); |
|
253 var map = m.map; |
|
254 var next = self.next; |
|
255 return { |
|
256 repr: function () { return "imap(...)"; }, |
|
257 toString: m.forwardCall("repr"), |
|
258 next: function () { |
|
259 return fun.apply(this, map(next, iterables)); |
|
260 } |
|
261 }; |
|
262 }, |
|
263 |
|
264 /** @id MochiKit.Iter.applymap */ |
|
265 applymap: function (fun, seq, self) { |
|
266 seq = MochiKit.Iter.iter(seq); |
|
267 var m = MochiKit.Base; |
|
268 return { |
|
269 repr: function () { return "applymap(...)"; }, |
|
270 toString: m.forwardCall("repr"), |
|
271 next: function () { |
|
272 return fun.apply(self, seq.next()); |
|
273 } |
|
274 }; |
|
275 }, |
|
276 |
|
277 /** @id MochiKit.Iter.chain */ |
|
278 chain: function (p, q/*, ...*/) { |
|
279 // dumb fast path |
|
280 var self = MochiKit.Iter; |
|
281 var m = MochiKit.Base; |
|
282 if (arguments.length == 1) { |
|
283 return self.iter(arguments[0]); |
|
284 } |
|
285 var argiter = m.map(self.iter, arguments); |
|
286 return { |
|
287 repr: function () { return "chain(...)"; }, |
|
288 toString: m.forwardCall("repr"), |
|
289 next: function () { |
|
290 while (argiter.length > 1) { |
|
291 try { |
|
292 var result = argiter[0].next(); |
|
293 return result; |
|
294 } catch (e) { |
|
295 if (e != self.StopIteration) { |
|
296 throw e; |
|
297 } |
|
298 argiter.shift(); |
|
299 var result = argiter[0].next(); |
|
300 return result; |
|
301 } |
|
302 } |
|
303 if (argiter.length == 1) { |
|
304 // optimize last element |
|
305 var arg = argiter.shift(); |
|
306 this.next = m.bind("next", arg); |
|
307 return this.next(); |
|
308 } |
|
309 throw self.StopIteration; |
|
310 } |
|
311 }; |
|
312 }, |
|
313 |
|
314 /** @id MochiKit.Iter.takewhile */ |
|
315 takewhile: function (pred, seq) { |
|
316 var self = MochiKit.Iter; |
|
317 seq = self.iter(seq); |
|
318 return { |
|
319 repr: function () { return "takewhile(...)"; }, |
|
320 toString: MochiKit.Base.forwardCall("repr"), |
|
321 next: function () { |
|
322 var rval = seq.next(); |
|
323 if (!pred(rval)) { |
|
324 this.next = function () { |
|
325 throw self.StopIteration; |
|
326 }; |
|
327 this.next(); |
|
328 } |
|
329 return rval; |
|
330 } |
|
331 }; |
|
332 }, |
|
333 |
|
334 /** @id MochiKit.Iter.dropwhile */ |
|
335 dropwhile: function (pred, seq) { |
|
336 seq = MochiKit.Iter.iter(seq); |
|
337 var m = MochiKit.Base; |
|
338 var bind = m.bind; |
|
339 return { |
|
340 "repr": function () { return "dropwhile(...)"; }, |
|
341 "toString": m.forwardCall("repr"), |
|
342 "next": function () { |
|
343 while (true) { |
|
344 var rval = seq.next(); |
|
345 if (!pred(rval)) { |
|
346 break; |
|
347 } |
|
348 } |
|
349 this.next = bind("next", seq); |
|
350 return rval; |
|
351 } |
|
352 }; |
|
353 }, |
|
354 |
|
355 _tee: function (ident, sync, iterable) { |
|
356 sync.pos[ident] = -1; |
|
357 var m = MochiKit.Base; |
|
358 var listMin = m.listMin; |
|
359 return { |
|
360 repr: function () { return "tee(" + ident + ", ...)"; }, |
|
361 toString: m.forwardCall("repr"), |
|
362 next: function () { |
|
363 var rval; |
|
364 var i = sync.pos[ident]; |
|
365 |
|
366 if (i == sync.max) { |
|
367 rval = iterable.next(); |
|
368 sync.deque.push(rval); |
|
369 sync.max += 1; |
|
370 sync.pos[ident] += 1; |
|
371 } else { |
|
372 rval = sync.deque[i - sync.min]; |
|
373 sync.pos[ident] += 1; |
|
374 if (i == sync.min && listMin(sync.pos) != sync.min) { |
|
375 sync.min += 1; |
|
376 sync.deque.shift(); |
|
377 } |
|
378 } |
|
379 return rval; |
|
380 } |
|
381 }; |
|
382 }, |
|
383 |
|
384 /** @id MochiKit.Iter.tee */ |
|
385 tee: function (iterable, n/* = 2 */) { |
|
386 var rval = []; |
|
387 var sync = { |
|
388 "pos": [], |
|
389 "deque": [], |
|
390 "max": -1, |
|
391 "min": -1 |
|
392 }; |
|
393 if (arguments.length == 1 || typeof(n) == "undefined" || n === null) { |
|
394 n = 2; |
|
395 } |
|
396 var self = MochiKit.Iter; |
|
397 iterable = self.iter(iterable); |
|
398 var _tee = self._tee; |
|
399 for (var i = 0; i < n; i++) { |
|
400 rval.push(_tee(i, sync, iterable)); |
|
401 } |
|
402 return rval; |
|
403 }, |
|
404 |
|
405 /** @id MochiKit.Iter.list */ |
|
406 list: function (iterable) { |
|
407 // Fast-path for Array and Array-like |
|
408 var rval; |
|
409 if (iterable instanceof Array) { |
|
410 return iterable.slice(); |
|
411 } |
|
412 // this is necessary to avoid a Safari crash |
|
413 if (typeof(iterable) == "function" && |
|
414 !(iterable instanceof Function) && |
|
415 typeof(iterable.length) == 'number') { |
|
416 rval = []; |
|
417 for (var i = 0; i < iterable.length; i++) { |
|
418 rval.push(iterable[i]); |
|
419 } |
|
420 return rval; |
|
421 } |
|
422 |
|
423 var self = MochiKit.Iter; |
|
424 iterable = self.iter(iterable); |
|
425 var rval = []; |
|
426 var a_val; |
|
427 try { |
|
428 while (true) { |
|
429 a_val = iterable.next(); |
|
430 rval.push(a_val); |
|
431 } |
|
432 } catch (e) { |
|
433 if (e != self.StopIteration) { |
|
434 throw e; |
|
435 } |
|
436 return rval; |
|
437 } |
|
438 // mozilla warnings aren't too bright |
|
439 return undefined; |
|
440 }, |
|
441 |
|
442 |
|
443 /** @id MochiKit.Iter.reduce */ |
|
444 reduce: function (fn, iterable, /* optional */initial) { |
|
445 var i = 0; |
|
446 var x = initial; |
|
447 var self = MochiKit.Iter; |
|
448 iterable = self.iter(iterable); |
|
449 if (arguments.length < 3) { |
|
450 try { |
|
451 x = iterable.next(); |
|
452 } catch (e) { |
|
453 if (e == self.StopIteration) { |
|
454 e = new TypeError("reduce() of empty sequence with no initial value"); |
|
455 } |
|
456 throw e; |
|
457 } |
|
458 i++; |
|
459 } |
|
460 try { |
|
461 while (true) { |
|
462 x = fn(x, iterable.next()); |
|
463 } |
|
464 } catch (e) { |
|
465 if (e != self.StopIteration) { |
|
466 throw e; |
|
467 } |
|
468 } |
|
469 return x; |
|
470 }, |
|
471 |
|
472 /** @id MochiKit.Iter.range */ |
|
473 range: function (/* [start,] stop[, step] */) { |
|
474 var start = 0; |
|
475 var stop = 0; |
|
476 var step = 1; |
|
477 if (arguments.length == 1) { |
|
478 stop = arguments[0]; |
|
479 } else if (arguments.length == 2) { |
|
480 start = arguments[0]; |
|
481 stop = arguments[1]; |
|
482 } else if (arguments.length == 3) { |
|
483 start = arguments[0]; |
|
484 stop = arguments[1]; |
|
485 step = arguments[2]; |
|
486 } else { |
|
487 throw new TypeError("range() takes 1, 2, or 3 arguments!"); |
|
488 } |
|
489 if (step === 0) { |
|
490 throw new TypeError("range() step must not be 0"); |
|
491 } |
|
492 return { |
|
493 next: function () { |
|
494 if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) { |
|
495 throw MochiKit.Iter.StopIteration; |
|
496 } |
|
497 var rval = start; |
|
498 start += step; |
|
499 return rval; |
|
500 }, |
|
501 repr: function () { |
|
502 return "range(" + [start, stop, step].join(", ") + ")"; |
|
503 }, |
|
504 toString: MochiKit.Base.forwardCall("repr") |
|
505 }; |
|
506 }, |
|
507 |
|
508 /** @id MochiKit.Iter.sum */ |
|
509 sum: function (iterable, start/* = 0 */) { |
|
510 if (typeof(start) == "undefined" || start === null) { |
|
511 start = 0; |
|
512 } |
|
513 var x = start; |
|
514 var self = MochiKit.Iter; |
|
515 iterable = self.iter(iterable); |
|
516 try { |
|
517 while (true) { |
|
518 x += iterable.next(); |
|
519 } |
|
520 } catch (e) { |
|
521 if (e != self.StopIteration) { |
|
522 throw e; |
|
523 } |
|
524 } |
|
525 return x; |
|
526 }, |
|
527 |
|
528 /** @id MochiKit.Iter.exhaust */ |
|
529 exhaust: function (iterable) { |
|
530 var self = MochiKit.Iter; |
|
531 iterable = self.iter(iterable); |
|
532 try { |
|
533 while (true) { |
|
534 iterable.next(); |
|
535 } |
|
536 } catch (e) { |
|
537 if (e != self.StopIteration) { |
|
538 throw e; |
|
539 } |
|
540 } |
|
541 }, |
|
542 |
|
543 /** @id MochiKit.Iter.forEach */ |
|
544 forEach: function (iterable, func, /* optional */obj) { |
|
545 var m = MochiKit.Base; |
|
546 var self = MochiKit.Iter; |
|
547 if (arguments.length > 2) { |
|
548 func = m.bind(func, obj); |
|
549 } |
|
550 // fast path for array |
|
551 if (m.isArrayLike(iterable) && !self.isIterable(iterable)) { |
|
552 try { |
|
553 for (var i = 0; i < iterable.length; i++) { |
|
554 func(iterable[i]); |
|
555 } |
|
556 } catch (e) { |
|
557 if (e != self.StopIteration) { |
|
558 throw e; |
|
559 } |
|
560 } |
|
561 } else { |
|
562 self.exhaust(self.imap(func, iterable)); |
|
563 } |
|
564 }, |
|
565 |
|
566 /** @id MochiKit.Iter.every */ |
|
567 every: function (iterable, func) { |
|
568 var self = MochiKit.Iter; |
|
569 try { |
|
570 self.ifilterfalse(func, iterable).next(); |
|
571 return false; |
|
572 } catch (e) { |
|
573 if (e != self.StopIteration) { |
|
574 throw e; |
|
575 } |
|
576 return true; |
|
577 } |
|
578 }, |
|
579 |
|
580 /** @id MochiKit.Iter.sorted */ |
|
581 sorted: function (iterable, /* optional */cmp) { |
|
582 var rval = MochiKit.Iter.list(iterable); |
|
583 if (arguments.length == 1) { |
|
584 cmp = MochiKit.Base.compare; |
|
585 } |
|
586 rval.sort(cmp); |
|
587 return rval; |
|
588 }, |
|
589 |
|
590 /** @id MochiKit.Iter.reversed */ |
|
591 reversed: function (iterable) { |
|
592 var rval = MochiKit.Iter.list(iterable); |
|
593 rval.reverse(); |
|
594 return rval; |
|
595 }, |
|
596 |
|
597 /** @id MochiKit.Iter.some */ |
|
598 some: function (iterable, func) { |
|
599 var self = MochiKit.Iter; |
|
600 try { |
|
601 self.ifilter(func, iterable).next(); |
|
602 return true; |
|
603 } catch (e) { |
|
604 if (e != self.StopIteration) { |
|
605 throw e; |
|
606 } |
|
607 return false; |
|
608 } |
|
609 }, |
|
610 |
|
611 /** @id MochiKit.Iter.iextend */ |
|
612 iextend: function (lst, iterable) { |
|
613 var m = MochiKit.Base; |
|
614 var self = MochiKit.Iter; |
|
615 if (m.isArrayLike(iterable) && !self.isIterable(iterable)) { |
|
616 // fast-path for array-like |
|
617 for (var i = 0; i < iterable.length; i++) { |
|
618 lst.push(iterable[i]); |
|
619 } |
|
620 } else { |
|
621 iterable = self.iter(iterable); |
|
622 try { |
|
623 while (true) { |
|
624 lst.push(iterable.next()); |
|
625 } |
|
626 } catch (e) { |
|
627 if (e != self.StopIteration) { |
|
628 throw e; |
|
629 } |
|
630 } |
|
631 } |
|
632 return lst; |
|
633 }, |
|
634 |
|
635 /** @id MochiKit.Iter.groupby */ |
|
636 groupby: function(iterable, /* optional */ keyfunc) { |
|
637 var m = MochiKit.Base; |
|
638 var self = MochiKit.Iter; |
|
639 if (arguments.length < 2) { |
|
640 keyfunc = m.operator.identity; |
|
641 } |
|
642 iterable = self.iter(iterable); |
|
643 |
|
644 // shared |
|
645 var pk = undefined; |
|
646 var k = undefined; |
|
647 var v; |
|
648 |
|
649 function fetch() { |
|
650 v = iterable.next(); |
|
651 k = keyfunc(v); |
|
652 }; |
|
653 |
|
654 function eat() { |
|
655 var ret = v; |
|
656 v = undefined; |
|
657 return ret; |
|
658 }; |
|
659 |
|
660 var first = true; |
|
661 var compare = m.compare; |
|
662 return { |
|
663 repr: function () { return "groupby(...)"; }, |
|
664 next: function() { |
|
665 // iterator-next |
|
666 |
|
667 // iterate until meet next group |
|
668 while (compare(k, pk) === 0) { |
|
669 fetch(); |
|
670 if (first) { |
|
671 first = false; |
|
672 break; |
|
673 } |
|
674 } |
|
675 pk = k; |
|
676 return [k, { |
|
677 next: function() { |
|
678 // subiterator-next |
|
679 if (v == undefined) { // Is there something to eat? |
|
680 fetch(); |
|
681 } |
|
682 if (compare(k, pk) !== 0) { |
|
683 throw self.StopIteration; |
|
684 } |
|
685 return eat(); |
|
686 } |
|
687 }]; |
|
688 } |
|
689 }; |
|
690 }, |
|
691 |
|
692 /** @id MochiKit.Iter.groupby_as_array */ |
|
693 groupby_as_array: function (iterable, /* optional */ keyfunc) { |
|
694 var m = MochiKit.Base; |
|
695 var self = MochiKit.Iter; |
|
696 if (arguments.length < 2) { |
|
697 keyfunc = m.operator.identity; |
|
698 } |
|
699 |
|
700 iterable = self.iter(iterable); |
|
701 var result = []; |
|
702 var first = true; |
|
703 var prev_key; |
|
704 var compare = m.compare; |
|
705 while (true) { |
|
706 try { |
|
707 var value = iterable.next(); |
|
708 var key = keyfunc(value); |
|
709 } catch (e) { |
|
710 if (e == self.StopIteration) { |
|
711 break; |
|
712 } |
|
713 throw e; |
|
714 } |
|
715 if (first || compare(key, prev_key) !== 0) { |
|
716 var values = []; |
|
717 result.push([key, values]); |
|
718 } |
|
719 values.push(value); |
|
720 first = false; |
|
721 prev_key = key; |
|
722 } |
|
723 return result; |
|
724 }, |
|
725 |
|
726 /** @id MochiKit.Iter.arrayLikeIter */ |
|
727 arrayLikeIter: function (iterable) { |
|
728 var i = 0; |
|
729 return { |
|
730 repr: function () { return "arrayLikeIter(...)"; }, |
|
731 toString: MochiKit.Base.forwardCall("repr"), |
|
732 next: function () { |
|
733 if (i >= iterable.length) { |
|
734 throw MochiKit.Iter.StopIteration; |
|
735 } |
|
736 return iterable[i++]; |
|
737 } |
|
738 }; |
|
739 }, |
|
740 |
|
741 /** @id MochiKit.Iter.hasIterateNext */ |
|
742 hasIterateNext: function (iterable) { |
|
743 return (iterable && typeof(iterable.iterateNext) == "function"); |
|
744 }, |
|
745 |
|
746 /** @id MochiKit.Iter.iterateNextIter */ |
|
747 iterateNextIter: function (iterable) { |
|
748 return { |
|
749 repr: function () { return "iterateNextIter(...)"; }, |
|
750 toString: MochiKit.Base.forwardCall("repr"), |
|
751 next: function () { |
|
752 var rval = iterable.iterateNext(); |
|
753 if (rval === null || rval === undefined) { |
|
754 throw MochiKit.Iter.StopIteration; |
|
755 } |
|
756 return rval; |
|
757 } |
|
758 }; |
|
759 } |
|
760 }); |
|
761 |
|
762 |
|
763 MochiKit.Iter.EXPORT_OK = [ |
|
764 "iteratorRegistry", |
|
765 "arrayLikeIter", |
|
766 "hasIterateNext", |
|
767 "iterateNextIter" |
|
768 ]; |
|
769 |
|
770 MochiKit.Iter.EXPORT = [ |
|
771 "StopIteration", |
|
772 "registerIteratorFactory", |
|
773 "iter", |
|
774 "count", |
|
775 "cycle", |
|
776 "repeat", |
|
777 "next", |
|
778 "izip", |
|
779 "ifilter", |
|
780 "ifilterfalse", |
|
781 "islice", |
|
782 "imap", |
|
783 "applymap", |
|
784 "chain", |
|
785 "takewhile", |
|
786 "dropwhile", |
|
787 "tee", |
|
788 "list", |
|
789 "reduce", |
|
790 "range", |
|
791 "sum", |
|
792 "exhaust", |
|
793 "forEach", |
|
794 "every", |
|
795 "sorted", |
|
796 "reversed", |
|
797 "some", |
|
798 "iextend", |
|
799 "groupby", |
|
800 "groupby_as_array" |
|
801 ]; |
|
802 |
|
803 MochiKit.Iter.__new__ = function () { |
|
804 var m = MochiKit.Base; |
|
805 // Re-use StopIteration if exists (e.g. SpiderMonkey) |
|
806 if (typeof(StopIteration) != "undefined") { |
|
807 this.StopIteration = StopIteration; |
|
808 } else { |
|
809 /** @id MochiKit.Iter.StopIteration */ |
|
810 this.StopIteration = new m.NamedError("StopIteration"); |
|
811 } |
|
812 this.iteratorRegistry = new m.AdapterRegistry(); |
|
813 // Register the iterator factory for arrays |
|
814 this.registerIteratorFactory( |
|
815 "arrayLike", |
|
816 m.isArrayLike, |
|
817 this.arrayLikeIter |
|
818 ); |
|
819 |
|
820 this.registerIteratorFactory( |
|
821 "iterateNext", |
|
822 this.hasIterateNext, |
|
823 this.iterateNextIter |
|
824 ); |
|
825 |
|
826 this.EXPORT_TAGS = { |
|
827 ":common": this.EXPORT, |
|
828 ":all": m.concat(this.EXPORT, this.EXPORT_OK) |
|
829 }; |
|
830 |
|
831 m.nameFunctions(this); |
|
832 |
|
833 }; |
|
834 |
|
835 MochiKit.Iter.__new__(); |
|
836 |
|
837 // |
|
838 // XXX: Internet Explorer blows |
|
839 // |
|
840 if (MochiKit.__export__) { |
|
841 reduce = MochiKit.Iter.reduce; |
|
842 } |
|
843 |
|
844 MochiKit.Base._exportSymbols(this, MochiKit.Iter); |