I'm trying to understand how yield works with recursion. For example, we have the following function in CoffeeScript that computes the factorial of a positive integer and returns the current cumulative product:
prod = 1
f = (n) ->
if n > 0
prod = n * prod
yield prod
f(n-1)
So if we call this function with a = f(3) and stepping through a.next(), I expect to see something like
{value: 3, done: false} // prod = 3 * 1
{value: 6, done: false} // prod = 3 * 2
{value: 6, done: true} // prod = 3 * 2 * 1
However, the actual output is
{value: 3, done: false}
{value: {}, done: false}
{value: undefined, done: true}
{value: undefined, done: true}
...
Could anyone explain what's going on here? And how I should change my code to get the desired results? Thanks!
@phenomnomnominal, as of CoffeeScript 1.9.1, there is "yield from" for "yield*":
prod = 1
f = (n) ->
if n > 0
prod = n * prod
yield prod
yield from f(n-1)
gen = f(3)
loop
ngen = gen.next()
console.log ngen
break if ngen.done
This should produce:
{ value: 3, done: false }
{ value: 6, done: false }
{ value: 6, done: false }
{ value: undefined, done: true }
I got this to work with the following in JS, running in FireFox:
var prod = 1;
var f = function*(n) {
if (n > 0) {
prod = n * prod;
yield prod;
yield* f(n - 1);
}
};
a = f(3);
console.log(a.next()); // Object { value: 3, done: false }
console.log(a.next()); // Object { value: 6, done: false }
console.log(a.next()); // Object { value: 6, done: false }
console.log(a.next()); // Object { value: undefined, done: true }
However, it looks as though CoffeeScript doesn't yet support yield*. Possibly a good chance for someone to contribute to the project! To get around this for now, you can use backticks to pass the JS through:
prod = 1
f = (n) ->
if n > 0
prod = n * prod
yield prod
`yield* f(n-1)`
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With