123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844 |
- /***
- MochiKit.Iter 1.4
- See <http://mochikit.com/> for documentation, downloads, license, etc.
- (c) 2005 Bob Ippolito. All rights Reserved.
- ***/
- if (typeof(dojo) != 'undefined') {
- dojo.provide('MochiKit.Iter');
- dojo.require('MochiKit.Base');
- }
- if (typeof(JSAN) != 'undefined') {
- JSAN.use("MochiKit.Base", []);
- }
- try {
- if (typeof(MochiKit.Base) == 'undefined') {
- throw "";
- }
- } catch (e) {
- throw "MochiKit.Iter depends on MochiKit.Base!";
- }
-
- if (typeof(MochiKit.Iter) == 'undefined') {
- MochiKit.Iter = {};
- }
-
- MochiKit.Iter.NAME = "MochiKit.Iter";
- MochiKit.Iter.VERSION = "1.4";
- MochiKit.Base.update(MochiKit.Iter, {
- __repr__: function () {
- return "[" + this.NAME + " " + this.VERSION + "]";
- },
- toString: function () {
- return this.__repr__();
- },
- /** @id MochiKit.Iter.registerIteratorFactory */
- registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
- MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
- },
- /** @id MochiKit.Iter.iter */
- iter: function (iterable, /* optional */ sentinel) {
- var self = MochiKit.Iter;
- if (arguments.length == 2) {
- return self.takewhile(
- function (a) { return a != sentinel; },
- iterable
- );
- }
- if (typeof(iterable.next) == 'function') {
- return iterable;
- } else if (typeof(iterable.iter) == 'function') {
- return iterable.iter();
- /*
- } else if (typeof(iterable.__iterator__) == 'function') {
- //
- // XXX: We can't support JavaScript 1.7 __iterator__ directly
- // because of Object.prototype.__iterator__
- //
- return iterable.__iterator__();
- */
- }
- try {
- return self.iteratorRegistry.match(iterable);
- } catch (e) {
- var m = MochiKit.Base;
- if (e == m.NotFound) {
- e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
- }
- throw e;
- }
- },
- /** @id MochiKit.Iter.count */
- count: function (n) {
- if (!n) {
- n = 0;
- }
- var m = MochiKit.Base;
- return {
- repr: function () { return "count(" + n + ")"; },
- toString: m.forwardCall("repr"),
- next: m.counter(n)
- };
- },
- /** @id MochiKit.Iter.cycle */
- cycle: function (p) {
- var self = MochiKit.Iter;
- var m = MochiKit.Base;
- var lst = [];
- var iterator = self.iter(p);
- return {
- repr: function () { return "cycle(...)"; },
- toString: m.forwardCall("repr"),
- next: function () {
- try {
- var rval = iterator.next();
- lst.push(rval);
- return rval;
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- if (lst.length === 0) {
- this.next = function () {
- throw self.StopIteration;
- };
- } else {
- var i = -1;
- this.next = function () {
- i = (i + 1) % lst.length;
- return lst[i];
- };
- }
- return this.next();
- }
- }
- };
- },
- /** @id MochiKit.Iter.repeat */
- repeat: function (elem, /* optional */n) {
- var m = MochiKit.Base;
- if (typeof(n) == 'undefined') {
- return {
- repr: function () {
- return "repeat(" + m.repr(elem) + ")";
- },
- toString: m.forwardCall("repr"),
- next: function () {
- return elem;
- }
- };
- }
- return {
- repr: function () {
- return "repeat(" + m.repr(elem) + ", " + n + ")";
- },
- toString: m.forwardCall("repr"),
- next: function () {
- if (n <= 0) {
- throw MochiKit.Iter.StopIteration;
- }
- n -= 1;
- return elem;
- }
- };
- },
-
- /** @id MochiKit.Iter.next */
- next: function (iterator) {
- return iterator.next();
- },
- /** @id MochiKit.Iter.izip */
- izip: function (p, q/*, ...*/) {
- var m = MochiKit.Base;
- var self = MochiKit.Iter;
- var next = self.next;
- var iterables = m.map(self.iter, arguments);
- return {
- repr: function () { return "izip(...)"; },
- toString: m.forwardCall("repr"),
- next: function () { return m.map(next, iterables); }
- };
- },
- /** @id MochiKit.Iter.ifilter */
- ifilter: function (pred, seq) {
- var m = MochiKit.Base;
- seq = MochiKit.Iter.iter(seq);
- if (pred === null) {
- pred = m.operator.truth;
- }
- return {
- repr: function () { return "ifilter(...)"; },
- toString: m.forwardCall("repr"),
- next: function () {
- while (true) {
- var rval = seq.next();
- if (pred(rval)) {
- return rval;
- }
- }
- // mozilla warnings aren't too bright
- return undefined;
- }
- };
- },
- /** @id MochiKit.Iter.ifilterfalse */
- ifilterfalse: function (pred, seq) {
- var m = MochiKit.Base;
- seq = MochiKit.Iter.iter(seq);
- if (pred === null) {
- pred = m.operator.truth;
- }
- return {
- repr: function () { return "ifilterfalse(...)"; },
- toString: m.forwardCall("repr"),
- next: function () {
- while (true) {
- var rval = seq.next();
- if (!pred(rval)) {
- return rval;
- }
- }
- // mozilla warnings aren't too bright
- return undefined;
- }
- };
- },
-
- /** @id MochiKit.Iter.islice */
- islice: function (seq/*, [start,] stop[, step] */) {
- var self = MochiKit.Iter;
- var m = MochiKit.Base;
- seq = self.iter(seq);
- var start = 0;
- var stop = 0;
- var step = 1;
- var i = -1;
- if (arguments.length == 2) {
- stop = arguments[1];
- } else if (arguments.length == 3) {
- start = arguments[1];
- stop = arguments[2];
- } else {
- start = arguments[1];
- stop = arguments[2];
- step = arguments[3];
- }
- return {
- repr: function () {
- return "islice(" + ["...", start, stop, step].join(", ") + ")";
- },
- toString: m.forwardCall("repr"),
- next: function () {
- var rval;
- while (i < start) {
- rval = seq.next();
- i++;
- }
- if (start >= stop) {
- throw self.StopIteration;
- }
- start += step;
- return rval;
- }
- };
- },
- /** @id MochiKit.Iter.imap */
- imap: function (fun, p, q/*, ...*/) {
- var m = MochiKit.Base;
- var self = MochiKit.Iter;
- var iterables = m.map(self.iter, m.extend(null, arguments, 1));
- var map = m.map;
- var next = self.next;
- return {
- repr: function () { return "imap(...)"; },
- toString: m.forwardCall("repr"),
- next: function () {
- return fun.apply(this, map(next, iterables));
- }
- };
- },
-
- /** @id MochiKit.Iter.applymap */
- applymap: function (fun, seq, self) {
- seq = MochiKit.Iter.iter(seq);
- var m = MochiKit.Base;
- return {
- repr: function () { return "applymap(...)"; },
- toString: m.forwardCall("repr"),
- next: function () {
- return fun.apply(self, seq.next());
- }
- };
- },
- /** @id MochiKit.Iter.chain */
- chain: function (p, q/*, ...*/) {
- // dumb fast path
- var self = MochiKit.Iter;
- var m = MochiKit.Base;
- if (arguments.length == 1) {
- return self.iter(arguments[0]);
- }
- var argiter = m.map(self.iter, arguments);
- return {
- repr: function () { return "chain(...)"; },
- toString: m.forwardCall("repr"),
- next: function () {
- while (argiter.length > 1) {
- try {
- return argiter[0].next();
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- argiter.shift();
- }
- }
- if (argiter.length == 1) {
- // optimize last element
- var arg = argiter.shift();
- this.next = m.bind("next", arg);
- return this.next();
- }
- throw self.StopIteration;
- }
- };
- },
- /** @id MochiKit.Iter.takewhile */
- takewhile: function (pred, seq) {
- var self = MochiKit.Iter;
- seq = self.iter(seq);
- return {
- repr: function () { return "takewhile(...)"; },
- toString: MochiKit.Base.forwardCall("repr"),
- next: function () {
- var rval = seq.next();
- if (!pred(rval)) {
- this.next = function () {
- throw self.StopIteration;
- };
- this.next();
- }
- return rval;
- }
- };
- },
- /** @id MochiKit.Iter.dropwhile */
- dropwhile: function (pred, seq) {
- seq = MochiKit.Iter.iter(seq);
- var m = MochiKit.Base;
- var bind = m.bind;
- return {
- "repr": function () { return "dropwhile(...)"; },
- "toString": m.forwardCall("repr"),
- "next": function () {
- while (true) {
- var rval = seq.next();
- if (!pred(rval)) {
- break;
- }
- }
- this.next = bind("next", seq);
- return rval;
- }
- };
- },
- _tee: function (ident, sync, iterable) {
- sync.pos[ident] = -1;
- var m = MochiKit.Base;
- var listMin = m.listMin;
- return {
- repr: function () { return "tee(" + ident + ", ...)"; },
- toString: m.forwardCall("repr"),
- next: function () {
- var rval;
- var i = sync.pos[ident];
- if (i == sync.max) {
- rval = iterable.next();
- sync.deque.push(rval);
- sync.max += 1;
- sync.pos[ident] += 1;
- } else {
- rval = sync.deque[i - sync.min];
- sync.pos[ident] += 1;
- if (i == sync.min && listMin(sync.pos) != sync.min) {
- sync.min += 1;
- sync.deque.shift();
- }
- }
- return rval;
- }
- };
- },
- /** @id MochiKit.Iter.tee */
- tee: function (iterable, n/* = 2 */) {
- var rval = [];
- var sync = {
- "pos": [],
- "deque": [],
- "max": -1,
- "min": -1
- };
- if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
- n = 2;
- }
- var self = MochiKit.Iter;
- iterable = self.iter(iterable);
- var _tee = self._tee;
- for (var i = 0; i < n; i++) {
- rval.push(_tee(i, sync, iterable));
- }
- return rval;
- },
- /** @id MochiKit.Iter.list */
- list: function (iterable) {
- // Fast-path for Array and Array-like
- var m = MochiKit.Base;
- if (typeof(iterable.slice) == 'function') {
- return iterable.slice();
- } else if (m.isArrayLike(iterable)) {
- return m.concat(iterable);
- }
- var self = MochiKit.Iter;
- iterable = self.iter(iterable);
- var rval = [];
- try {
- while (true) {
- rval.push(iterable.next());
- }
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- return rval;
- }
- // mozilla warnings aren't too bright
- return undefined;
- },
-
- /** @id MochiKit.Iter.reduce */
- reduce: function (fn, iterable, /* optional */initial) {
- var i = 0;
- var x = initial;
- var self = MochiKit.Iter;
- iterable = self.iter(iterable);
- if (arguments.length < 3) {
- try {
- x = iterable.next();
- } catch (e) {
- if (e == self.StopIteration) {
- e = new TypeError("reduce() of empty sequence with no initial value");
- }
- throw e;
- }
- i++;
- }
- try {
- while (true) {
- x = fn(x, iterable.next());
- }
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- }
- return x;
- },
- /** @id MochiKit.Iter.range */
- range: function (/* [start,] stop[, step] */) {
- var start = 0;
- var stop = 0;
- var step = 1;
- if (arguments.length == 1) {
- stop = arguments[0];
- } else if (arguments.length == 2) {
- start = arguments[0];
- stop = arguments[1];
- } else if (arguments.length == 3) {
- start = arguments[0];
- stop = arguments[1];
- step = arguments[2];
- } else {
- throw new TypeError("range() takes 1, 2, or 3 arguments!");
- }
- if (step === 0) {
- throw new TypeError("range() step must not be 0");
- }
- return {
- next: function () {
- if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
- throw MochiKit.Iter.StopIteration;
- }
- var rval = start;
- start += step;
- return rval;
- },
- repr: function () {
- return "range(" + [start, stop, step].join(", ") + ")";
- },
- toString: MochiKit.Base.forwardCall("repr")
- };
- },
-
- /** @id MochiKit.Iter.sum */
- sum: function (iterable, start/* = 0 */) {
- if (typeof(start) == "undefined" || start === null) {
- start = 0;
- }
- var x = start;
- var self = MochiKit.Iter;
- iterable = self.iter(iterable);
- try {
- while (true) {
- x += iterable.next();
- }
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- }
- return x;
- },
-
- /** @id MochiKit.Iter.exhaust */
- exhaust: function (iterable) {
- var self = MochiKit.Iter;
- iterable = self.iter(iterable);
- try {
- while (true) {
- iterable.next();
- }
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- }
- },
- /** @id MochiKit.Iter.forEach */
- forEach: function (iterable, func, /* optional */self) {
- var m = MochiKit.Base;
- if (arguments.length > 2) {
- func = m.bind(func, self);
- }
- // fast path for array
- if (m.isArrayLike(iterable)) {
- try {
- for (var i = 0; i < iterable.length; i++) {
- func(iterable[i]);
- }
- } catch (e) {
- if (e != MochiKit.Iter.StopIteration) {
- throw e;
- }
- }
- } else {
- self = MochiKit.Iter;
- self.exhaust(self.imap(func, iterable));
- }
- },
- /** @id MochiKit.Iter.every */
- every: function (iterable, func) {
- var self = MochiKit.Iter;
- try {
- self.ifilterfalse(func, iterable).next();
- return false;
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- return true;
- }
- },
- /** @id MochiKit.Iter.sorted */
- sorted: function (iterable, /* optional */cmp) {
- var rval = MochiKit.Iter.list(iterable);
- if (arguments.length == 1) {
- cmp = MochiKit.Base.compare;
- }
- rval.sort(cmp);
- return rval;
- },
- /** @id MochiKit.Iter.reversed */
- reversed: function (iterable) {
- var rval = MochiKit.Iter.list(iterable);
- rval.reverse();
- return rval;
- },
- /** @id MochiKit.Iter.some */
- some: function (iterable, func) {
- var self = MochiKit.Iter;
- try {
- self.ifilter(func, iterable).next();
- return true;
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- return false;
- }
- },
- /** @id MochiKit.Iter.iextend */
- iextend: function (lst, iterable) {
- if (MochiKit.Base.isArrayLike(iterable)) {
- // fast-path for array-like
- for (var i = 0; i < iterable.length; i++) {
- lst.push(iterable[i]);
- }
- } else {
- var self = MochiKit.Iter;
- iterable = self.iter(iterable);
- try {
- while (true) {
- lst.push(iterable.next());
- }
- } catch (e) {
- if (e != self.StopIteration) {
- throw e;
- }
- }
- }
- return lst;
- },
- /** @id MochiKit.Iter.groupby */
- groupby: function(iterable, /* optional */ keyfunc) {
- var m = MochiKit.Base;
- var self = MochiKit.Iter;
- if (arguments.length < 2) {
- keyfunc = m.operator.identity;
- }
- iterable = self.iter(iterable);
- // shared
- var pk = undefined;
- var k = undefined;
- var v;
- function fetch() {
- v = iterable.next();
- k = keyfunc(v);
- };
- function eat() {
- var ret = v;
- v = undefined;
- return ret;
- };
- var first = true;
- var compare = m.compare;
- return {
- repr: function () { return "groupby(...)"; },
- next: function() {
- // iterator-next
- // iterate until meet next group
- while (compare(k, pk) === 0) {
- fetch();
- if (first) {
- first = false;
- break;
- }
- }
- pk = k;
- return [k, {
- next: function() {
- // subiterator-next
- if (v == undefined) { // Is there something to eat?
- fetch();
- }
- if (compare(k, pk) !== 0) {
- throw self.StopIteration;
- }
- return eat();
- }
- }];
- }
- };
- },
- /** @id MochiKit.Iter.groupby_as_array */
- groupby_as_array: function (iterable, /* optional */ keyfunc) {
- var m = MochiKit.Base;
- var self = MochiKit.Iter;
- if (arguments.length < 2) {
- keyfunc = m.operator.identity;
- }
- iterable = self.iter(iterable);
- var result = [];
- var first = true;
- var prev_key;
- var compare = m.compare;
- while (true) {
- try {
- var value = iterable.next();
- var key = keyfunc(value);
- } catch (e) {
- if (e == self.StopIteration) {
- break;
- }
- throw e;
- }
- if (first || compare(key, prev_key) !== 0) {
- var values = [];
- result.push([key, values]);
- }
- values.push(value);
- first = false;
- prev_key = key;
- }
- return result;
- },
- /** @id MochiKit.Iter.arrayLikeIter */
- arrayLikeIter: function (iterable) {
- var i = 0;
- return {
- repr: function () { return "arrayLikeIter(...)"; },
- toString: MochiKit.Base.forwardCall("repr"),
- next: function () {
- if (i >= iterable.length) {
- throw MochiKit.Iter.StopIteration;
- }
- return iterable[i++];
- }
- };
- },
- /** @id MochiKit.Iter.hasIterateNext */
- hasIterateNext: function (iterable) {
- return (iterable && typeof(iterable.iterateNext) == "function");
- },
- /** @id MochiKit.Iter.iterateNextIter */
- iterateNextIter: function (iterable) {
- return {
- repr: function () { return "iterateNextIter(...)"; },
- toString: MochiKit.Base.forwardCall("repr"),
- next: function () {
- var rval = iterable.iterateNext();
- if (rval === null || rval === undefined) {
- throw MochiKit.Iter.StopIteration;
- }
- return rval;
- }
- };
- }
- });
- MochiKit.Iter.EXPORT_OK = [
- "iteratorRegistry",
- "arrayLikeIter",
- "hasIterateNext",
- "iterateNextIter",
- ];
- MochiKit.Iter.EXPORT = [
- "StopIteration",
- "registerIteratorFactory",
- "iter",
- "count",
- "cycle",
- "repeat",
- "next",
- "izip",
- "ifilter",
- "ifilterfalse",
- "islice",
- "imap",
- "applymap",
- "chain",
- "takewhile",
- "dropwhile",
- "tee",
- "list",
- "reduce",
- "range",
- "sum",
- "exhaust",
- "forEach",
- "every",
- "sorted",
- "reversed",
- "some",
- "iextend",
- "groupby",
- "groupby_as_array"
- ];
- MochiKit.Iter.__new__ = function () {
- var m = MochiKit.Base;
- // Re-use StopIteration if exists (e.g. SpiderMonkey)
- if (typeof(StopIteration) != "undefined") {
- this.StopIteration = StopIteration;
- } else {
- /** @id MochiKit.Iter.StopIteration */
- this.StopIteration = new m.NamedError("StopIteration");
- }
- this.iteratorRegistry = new m.AdapterRegistry();
- // Register the iterator factory for arrays
- this.registerIteratorFactory(
- "arrayLike",
- m.isArrayLike,
- this.arrayLikeIter
- );
- this.registerIteratorFactory(
- "iterateNext",
- this.hasIterateNext,
- this.iterateNextIter
- );
- this.EXPORT_TAGS = {
- ":common": this.EXPORT,
- ":all": m.concat(this.EXPORT, this.EXPORT_OK)
- };
- m.nameFunctions(this);
-
- };
- MochiKit.Iter.__new__();
- //
- // XXX: Internet Explorer blows
- //
- if (MochiKit.__export__) {
- reduce = MochiKit.Iter.reduce;
- }
- MochiKit.Base._exportSymbols(this, MochiKit.Iter);
|