Почему генераторы не поддерживают 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;
};
Их должно хватить для начала и наиболее распространенных вариантов использования. Правильная библиотека распространит это на генераторы так, чтобы значения передавались соответствующим образом, а также решит проблему, заключающуюся в том, что итераторы могут использоваться только один раз, пока они не будут исчерпаны (в отличие от массивов).