如何排空发电机?

时间:2019-01-11 21:02:16

标签: javascript ecmascript-6 iteration generator

我将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

这似乎很麻烦,因为我必须为每个迭代函数实现一个单独的排气函数。这是否表明发电机使用不正确?

3 个答案:

答案 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...

如果代码面对永无休止的生成器,那么代码的行为应该是什么?