Рекурсивные генераторы в JavaScript
Я пытаюсь написать рекурсивный генератор для прохождения заказа.
class Tree {
*inOrderTraversal() {
function* helper(node) {
if (node.left !== null) {
// this line is executed, but helper is not being called
helper(node.left);
}
yield node.value;
if (node.right !== null) {
helper(node.right);
}
}
for (let i of helper(this.root)) {
yield i;
}
}
// other methods omitted
}
и я вызываю генератор так:
const tree = new Tree();
tree.add(2);
tree.add(1);
tree.add(3);
for (let i of tree.inOrderTraversal()) {
console.log(i); // only prints 2
}
почему генератор только уступает 2
? Почему это как минимум не уступая 1
до 2
?
как я могу это исправить?
если это поможет, я транспилирую код с помощью babel.
babel --optional runtime test.js | node
2 ответов
проблема была не в рекурсии. Ваша функция сделал вызовите себя рекурсивно, он просто не дал значений снаружи. Когда вы вызываете helper (), вы получаете итератор в качестве возвращаемого значения, но вы хотели, чтобы итерационные значения этого итератора были получены. Если вы хотите уступить рекурсивно, вам нужно yield *
. Попробуйте так:
* inOrderTraversal() {
function* helper(node) {
if (node.left !== null) {
// this line is executed, but helper is not being called
yield * helper(node.left);
}
yield node.value;
if (node.right !== null) {
yield * helper(node.right);
}
}
for (let i of helper(this.root)) {
yield i;
}
}
и пока вы на него, вы можете заменить for
петли с:
yield * helper(this.root)
helper(node.left);
вызывает функцию и создает генератор, но тело функции генератора никогда не выполняется, потому что генератор никогда не расширяется. Чтобы переслать все его значения генератору тока, вы можете использовать yield*
ключевое слово, который работает так же, как
for (let i of helper(this.root))
yield i;
вы использовали в своей inOrderTraversal
метод. И действительно, это должно было быть yield*
так же хорошо или даже лучше, нет никаких причин, чтобы сделать inOrderTraversal
функция генератора, когда он может просто будьте обычным методом, который возвращает генератор:
class Tree {
inOrderTraversal() {
function* helper(node) {
if (node.left !== null)
yield* helper(node.left);
yield node.value;
if (node.right !== null)
yield* helper(node.right);
}
return helper(this.root);
}
… // other methods
}