我将every
用作生成器来过早中断迭代:
const every = (f, iter) => function* () {
for (const value of iter) {
const ret = f(value);
yield ret;
if (!ret) break;
}
} ();
const exhaustEvery = iter => {
for (value of iter) {
if (!value)
return false;
}
return true;
};
exhaustEvery(every(x => x % 2 === 1, [1,3,5])); // true
这似乎很麻烦,因为我必须为每个迭代函数实现一个单独的排气函数。这是否表明发电机使用不正确?
答案 0 :(得分:2)
every
是一个生成器几乎没有意义,因为它本身并不生成值,它只返回true或false,因此可能是:
function every(iterator, predicate) {
let value, done;
do {
({ value, done } = iterator.next());
if(!predicate(value)) return false;
} while(!done)
return true;
}
every([1, 2, 3].values(), it => it < 3) // false
答案 1 :(得分:1)
如果您知道生成器将结束(生成器不保证),则可以使用[...res]
扩展值。如果是生成器,则只需查看最后一个值即可:
const every = (f, iter) => function*() {
for (const value of iter) {
const ret = f(value);
yield ret;
if (!ret) break;
}
}();
let res = [...every(x => x % 2 === 1, [1, 3, 5])]; // true
console.log(res[res.length - 1])
res = [...every(x => x % 2 === 1, [1, 3, 5, 8, 2, 5, 9])]; // false
console.log(res[res.length - 1])
但是,如果您只是为了从生成器生成列表而进行所有操作,那么使用简单函数可能会有更好的方法。
答案 2 :(得分:0)
有些发电机不能用光,例如:
function *fibonacci(n) {
const infinite = !n && n !== 0;
let current = 0;
let next = 1;
while (infinite || n--) {
yield current;
[current, next] = [next, current + next];
}
}
// let [...first10] = fibonacci(10);
// alert(first10);
// the above is finite generator and shows how you can exhaust it,
// but what if it is initiated like the following:
let noexhaust = fibonacci();
alert(noexhaust.next().value);
alert(noexhaust.next().value);
alert(noexhaust.next().value);
alert(noexhaust.next().value);
// and so on...
如果代码面对永无休止的生成器,那么代码的行为应该是什么?