Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I yield from an inner function?

People also ask

What is yield in generator function?

The yield keyword pauses generator function execution and the value of the expression following the yield keyword is returned to the generator's caller. It can be thought of as a generator-based version of the return keyword. yield can only be called directly from the generator function that contains it.

Is yield a generator?

Yield is a keyword in Python that is used to return from a function without destroying the states of its local variable and when the function is called, the execution starts from the last yield statement. Any function that contains a yield keyword is termed a generator. Hence, yield is what makes a generator.

How do you yield in Python?

yield in Python can be used like the return statement in a function. When done so, the function instead of returning the output, it returns a generator that can be iterated upon. You can then iterate through the generator to extract items. Iterating is done using a for loop or simply using the next() function.

What is the difference between the await keyword and the yield keyword?

A generator function is executed yield by yield i.e one yield-expression at a time by its iterator (the next method) whereas async-await, they are executed sequential await by await. Async/await makes it easier to implement a particular use case of Generators.


No, you can't use yield inside of the inner function. But in your case you don't need it. You can always use for-of loop instead of forEach method. It will look much prettier, and you can use continue, break, yield inside it:

var trivialGenerator = function *(array) {
    for (var item of array) {
        // some item manipulation
        yield item;
    }
}

You can use for-of if you have some manipulations with item inside it. Otherwise you absolutely don't need to create this generator, as array has iterator interface natively.


No, you can't yield from a callback (technically, it's not an "inner function", which means something else). There's obviously no way to call forEach with the equivalent of *, or, if the callback itself is a generator, to tell forEach to invoke the callback with yield *.

One alternative is to write a function forEachGen, as follows:

function *forEachGen(array, fn) { for (var i of array) yield *fn(i); }

essentially moving the for-loop into forEachGen. Defining a little sample generator as

function *yieldSelf(item) { yield item; }

forEachGen would be used as

yield *forEachGen(array, yieldSelf);

This assumes the callback is a generator itself, as you seem to imply you want in your example. If the callback were a ROF (regular old function), such as

function returnSelf(item) { return item; }

Then it would be

function *forEachGen(array, fn) { for (var i of array) yield fn(i); }

used as

yield *forEachGen(array, returnSelf);

If you don't mind adding this to the array prototype, then

Object.defineProperty(Array.prototype, 'forEachGen', { value :
    function *(fn) { for (i of this) yield fn(i); }
});

then do

yield *array.forEachGen(yieldSelf)

You may be interested in http://fitzgen.github.io/wu.js/, which defines a wrapper for generators with methods such as forEach on the wrapper.

async / await

With await, you should be able to do the following.

Define a trivial callback which just returns a promise for itself.

async function returnSelf(item) { return await item; }

forEachAsync maps the input array into an array of promises, and uses await * to create and return a promise for all the individual promises being ready.

async function forEachAsync(values, fn) {
  return await *values.map(returnSelf);
}

We can treat the result as a regular promise and print it out in a then:

forEachAsync([1,2,3], returnSelf) .
  then(result => console.log(result);

or use a little IIFE async wrapper to do wait for the result and then print it out:

(async function() { 
    console.log(await forEachAsync([1,2,3], returnSelf));
})();

Tested using

babel-node --experimental test.js