Отображение функции на генераторе в JavaScript

У меня есть генератор с именем generateNumbers в JavaScript и еще один генератор generateLargerNumbers, который принимает каждое значение, сгенерированное с помощью generateNumbers, и применяет к нему функцию addOne, как таковую:

function addOne(value) {
  return value + 1
}

function* generateNumbers() {
  yield 1
  yield 2
  yield 3
}

function* generateLargerNumbers() {
  for (const number of generateNumbers()) {
    yield addOne(number)
  }
}

Есть ли способ сделать это без создания массива из сгенерированных значений? Я думаю что-то вроде:

function* generateLargerNumbers() {
  yield* generateNumbers().map(addOne) // obviously doesn't work
}

Ответ 1

Нет встроенного способа сопоставления объектов Generator, но вы можете свернуть свою собственную функцию:

const Generator = Object.getPrototypeOf(function* () {});
Generator.prototype.map = function* (mapper, thisArg) {
  for (const val of this) {
    yield mapper.call(thisArg, val);
  }
};

Теперь вы можете сделать:

function generateLargerNumbers() {
  return generateNumbers().map(addOne);
}

const Generator = Object.getPrototypeOf(function* () {});
Generator.prototype.map = function* (mapper, thisArg) {
  for (const val of this) {
    yield mapper.call(thisArg, val);
  }
};

function addOne(value) {
  return value + 1
}

function* generateNumbers() {
  yield 1
  yield 2
  yield 3
}

function generateLargerNumbers() {
  return generateNumbers().map(addOne)
}

console.log(...generateLargerNumbers())

Ответ 2

генераторы более высокого порядка

Вы можете сами управлять функциями генератора

const Generator =
  {
    map: (f,g) => function* (...args)
      {
        for (const x of g (...args))
          yield f (x)
      },
    filter: (f,g) => function* (...args)
      {
        for (const x of g (...args))
          if (f (x))
            yield x
      }
  }

// some functions !
const square = x =>
  x * x

const isEven = x =>
  (x & 1) === 0
  
// a generator !
const range = function* (x = 0, y = 1)
  {
    while (x < y)
      yield x++
  }

// higher order generator !
for (const x of Generator.map (square, Generator.filter (isEven, range)) (0,10))
  console.log('evens squared', x)

Ответ 3

Как о создании объекта итератора вместо использования вложенных генераторов?

function* generateNumbers(){
 yield 1;   
 yield 2;
 yield 3;
}

function generateGreaterNumbers(){
 return { next(){ var r = this.gen.next(); r.value+=1; return r; }, gen: generateNumbers() };`
}