Iterator 为什么生成器不支持map()?

Iterator 为什么生成器不支持map()?,iterator,generator,ecmascript-6,map-function,Iterator,Generator,Ecmascript 6,Map Function,在我看来,生成器(其功能非常类似于数组)应该支持非常基本的列表操作,如map()、filter()、和reduce()。我错过什么了吗 我为map编写了代码,看起来很简单,但最好将所有函数嵌入到所有生成器中: let fancyGen = g => { let rv = function*() { for (let x of g) yield x; } rv.map = function*(p) { for (let x of g) y

在我看来,生成器(其功能非常类似于数组)应该支持非常基本的列表操作,如
map()
filter()
、和
reduce()
。我错过什么了吗

我为
map
编写了代码,看起来很简单,但最好将所有函数嵌入到所有生成器中:

let fancyGen = g => {
  let rv = function*() {
    for (let x of g) 
      yield x;
  }
  rv.map = function*(p) {
   for (let x of g) 
      yield p(x);
  } 
  return rv;
}
我不熟悉生成器,所以欢迎对代码发表任何评论。特别是,这是编写“身份生成器”的最佳方式吗

为什么生成器不支持map()

因为它太容易填写为用户区实现。ES3也没有包含数组迭代方法,可能会在ES7中看到迭代器的转换器:-)

生成器,其功能非常类似于阵列

否,请停止并区分迭代器和生成器:

let fancyGen = g => {
  let rv = function*() {
    for (let x of g) 
      yield x;
  }
  rv.map = function*(p) {
   for (let x of g) 
      yield p(x);
  } 
  return rv;
}
  • 迭代器是具有符合迭代器协议的
    .next()
    方法的对象
  • 生成器是由生成器函数(
    函数*
    )创建的迭代器。它的
    .next()
    方法接受一个参数,该参数是生成器函数中每个
    yield
    的结果。它还有
    .return()
    .throw()
    方法
您最感兴趣的是迭代器,在迭代器中,我们不会将值传递给
下一个
,也不关心最终结果,就像
for of
循环一样。我们可以使用所需的方法轻松地扩展它们:

var IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
IteratorPrototype.map = function*(f) {
    for (var x of this)
        yield f(x);
};
IteratorPrototype.filter = function*(p) {
    for (var x of this)
        if (p(x))
            yield x;
};
IteratorPrototype.scan = function*(f, acc) {
    for (var x of this)
        yield acc = f(acc, x);
    return acc;
};
IteratorPrototype.reduce = function(f, acc) {
    for (var x of this)
        acc = f(acc, x);
    return acc;
};

这些应该足以满足最开始和最常见的用例。一个合适的库可以将其扩展到生成器,以便适当地传递值,还可以解决迭代器在耗尽之前只能使用一次的问题(与数组不同)。

区分生成器和迭代器就像区分贵宾犬和狗一样——贵宾犬就是狗,虽然不是所有的狗都是卷毛狗。与犬科动物的情况相反,不是生成器的迭代器古怪且难以使用,因此我将兴趣限制在生成器上(以及通过
for..of
语法进行访问)不应该是生成器函数。@Malvolio:事实上,生成器比日常迭代器更古怪,更难使用。您很少遇到它们-所有
[Symbol.iterator]
方法都返回迭代器,而不是生成器。通过的访问发电机不会使用其全部功率。