Ответ 1
Может ли кто-нибудь найти какие-либо очевидные проблемы, которые мне не хватает здесь?
fact
возвращает итератор, но вы пытаетесь его несколько с номером: n * fact(n-1)
. Это не сработает!
Поскольку fact
возвращает итератор, но вы также хотите умножить последнее значение итератора на n
(т.е. оно не является хвостовым рекурсивным), вы также не можете просто yield*
его.
Вам нужно явно перебрать результат из внутреннего вызова, повторно использовать значение и запомнить последнее значение, чтобы вы могли с ним несколько:
function* fact (n) {
if (n < 2) {
yield 1;
} else {
let last;
for(last of fact(n-1)) {
yield last;
}
yield n * last;
}
}
Array.from(fact(5)); // [1, 2, 6, 24, 120]
Если вы измените функцию на хвостовую рекурсивность, она будет немного короче (и лучше), но результат будет также другим (поскольку мы выполняем операции в другом порядке, по крайней мере, в этой реализации):
function* fact (n, acc=1) {
yield acc
if (n > 1) {
yield* fact(n-1, acc * n);
}
}
Array.from(fact(5)); // [1, 5, 20, 60, 120]
Лично я бы просто написал нерекурсивную версию:
function* fact (n) {
let result = 1;
let i = 0;
while (i < n) {
yield result = result * ++i;
}
}
Array.from(fact(5)); // [1, 2, 6, 24, 120]