paco_sako/js/iterator.js

137 lines
2.9 KiB
JavaScript

'use strict';
export const IteratorMixin = {
map: function* map(f) {
let y;
while (!(y = this.next()).done) {
yield f(y.value);
}
return y.value;
},
filter: function* filter(f) {
let y;
while (!(y = this.next()).done) {
if (f(y.value)) {
yield y.value;
}
}
return y.value;
},
take: function* take(limit) {
let remaining = Number(limit) & -1;
let y;
while (remaining > 0 && !(y = this.next()).done) {
yield y.value;
remaining -= 1;
}
},
drop: function* drop(limit) {
let remaining = Number(limit) & -1;
let y;
while (!(y = this.next()).done) {
if (remaining <= 0) {
yield y.value;
} else {
remaining -= 1;
}
}
},
asIndexedPairs: function* asIndexedPairs() {
let index = 0;
let y;
while (!(y = this.next()).done) {
yield [index++, x];
}
return y.value;
},
flatMap: function* flatMap(f) {
let y;
while (!(y = this.next()).done) {
yield* f(y.value);
}
return y.value;
},
reduce: function reduce(f, state) {
if (typeof state === 'undefined') {
const first = this.next();
if (first.done) {
throw new TypeError('reduce: empty iterator');
}
state = first.value;
}
let y;
while (!(y = this.next()).done) {
state = f(state, y.value);
}
return state;
},
toArray: function toArray() {
return [...this];
},
forEach: function* forEach(f) {
let y;
while (!(y = this.next()).done) {
f(y.value);
}
},
some: function some(f) {
/* extension: if f is undefined, assume identity function */
let iter = (typeof f === 'undefined') ? this : IteratorMixin.map.call(this, f);
let y;
while (!(y = iter.next()).done) {
if (y.value) {
return true;
}
}
return false;
},
every: function every(f) {
/* extension: if f is undefined, assume identity function */
let iter = (typeof f === 'undefined') ? this : IteratorMixin.map.call(this, f);
let y;
while (!(y = iter.next()).done) {
if (!y.value) {
return false;
}
}
return true;
},
find: function find(f) {
if (typeof f === undefined) {
/* extension */
f = function identity(x) { return x; };
}
let y;
while (!(y = this.next()).done) {
if (f(y.value)) {
return y.value;
}
}
},
/* extension */
includes: function includes(x) {
return IteratorMixin.some.call(this, function equalsX(y) { return y === x; });
},
};
export const Iterator = {};
for (const fn in IteratorMixin) {
Iterator[fn] = function() {
return IteratorMixin[fn].call(...arguments);
};
}
export default Iterator;