Почему генераторы не поддерживают map()?

Мне кажется совершенно естественным, что генераторы, которые очень похожи на массивы, должны поддерживать самые простые операции со списками, такие как 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;
}

Я новичок в генераторах, поэтому любые комментарии к коду приветствуются. В частности, это лучший способ написать "генератор идентичности"?

1 ответ

Почему генераторы не поддерживают map()?

Потому что это слишком легко заполнить как пользовательскую реализацию. ES3 не включал итерационные методы Array, может быть, увидим преобразователи для итераторов в ES7:-)

генераторы, которые очень похожи на массивы

Нет, остановите и отличите итераторы от генераторов:

  • Итератор - это объект с .next() метод, соответствующий протоколу итератора.
  • Генератор - это итератор, созданный функцией генератора (function*). это .next() Метод принимает аргумент, который является результатом каждого yield внутри функции генератора. Он также имеет .return() а также .throw() методы.

В основном вы будете заинтересованы в итераторах, где мы не передаем значения nextи не заботится о конечном результате - так же, как 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;
};

Их должно хватить для начала и наиболее распространенных вариантов использования. Правильная библиотека распространит это на генераторы так, чтобы значения передавались соответствующим образом, а также решит проблему, заключающуюся в том, что итераторы могут использоваться только один раз, пока они не будут исчерпаны (в отличие от массивов).

Другие вопросы по тегам