Skip to content

Instantly share code, notes, and snippets.

@ianmstew
Last active November 30, 2022 14:56
Show Gist options
  • Save ianmstew/455b1b354cb0186becd0d340d4f90bb6 to your computer and use it in GitHub Desktop.
Save ianmstew/455b1b354cb0186becd0d340d4f90bb6 to your computer and use it in GitHub Desktop.
(() => {
function MappedYieldGenerator(generator, mapYield) {
return function*() {
const gen = generator();
let genResult;
let resolvedValue;
do {
genResult = gen.next(resolvedValue);
resolvedValue = yield mapYield(genResult.value);
} while (!genResult.done);
return resolvedValue;
};
}
function* oneTwoThree() {
yield 1;
yield 2;
yield 3;
}
const twoThreeFour = MappedYieldGenerator(oneTwoThree, (val) => val + 1);
const gen = oneTwoThree();
console.log(gen.next().value, gen.next().value, gen.next().value);
// => 1 2 3
const gen2 = twoThreeFour();
console.log(gen2.next().value, gen2.next().value, gen2.next().value);
// => 2 3 4
})()
@getify
Copy link

getify commented Nov 30, 2022

Here's an alternative implementation to consider:

function MappedYieldGenerator(generator, mapYield) {
  return function*() {
    for (let v of generator()) {
        yield mapYield(v);
    } 
  };
}

One small downside is that any final return from the original generator is not returned through the mapped generator with this approach.

But such a value-return is ill-advised anyway, since the consumption side of the iterator protocol (for-of, ..., Array.from) would ignore/throw away such return values.

I think the simpler implementation I showed more clearly illustrates the semantic relationship when iterators are lazily composed like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment