I came up with this simple experiment after reading the documentation on generators from MDN:
var nodes = {
type: \'root\',
value: [
{ type: \
You've found your solution, but just for the record here is another example a little different that print the types of all nodes in the tree (I added some deepness and vars)
var nodes = {
type: 'root',
value: [
{ type: 'char', value: 'a' },
{ type: 'char', value: 'b' },
{ type: 'char', value: [{type: 'int', value: 'c'}] },
],
};
var flattenTree = function* (root) {
yield root.type;
var subvalues = root.value;
for(var i in subvalues) {
var gen = flattenTree(subvalues[i]);
val = gen.next();
while(!val.done) {
if(val.value != undefined)
yield val.value;
val = gen.next();
}
}
}
var printTree = function() {
console.log("begin tree");
var generator = flattenTree(nodes);
var next = generator.next();
while(!next.done) {
console.log(next);
next = generator.next();
}
console.log("finish tree");
}
printTree();
Outputs:
~/workspace/tmp$ ../node/node --harmony test-gen.js
begin tree
{ value: 'root', done: false }
{ value: 'char', done: false }
{ value: 'char', done: false }
{ value: 'char', done: false }
{ value: 'int', done: false }
finish tree
Summarizing the comments: you can't use yield
inside a regular function, so you can't use yield
with forEach
. Here an example of "generatorized" foreach:
function * foreach (arr, fn) {
var i
for (i = 0; i < arr.length; i++) {
yield * fn(arr[i])
}
}
function * gen (number) {
yield number + 1
yield number + 2
yield number + 3
}
function * other () {
yield * foreach([1, 2, 3], gen)
}
for (var i of other()) {
console.log(i)
}
UPDATE Also the original problem can be solved quite elegantly using such a helper:
var nodes = {
type: 'root',
value: [
{ type: 'char', value: 'a' },
{ type: 'char', value: 'b' },
{ type: 'root', value: [
{ type: 'char', value: 'c' },
{ type: 'char', value: 'd' },
{ type: 'char', value: 'e' },
]
},
],
}
function * foreach (arr, fn) {
var i
for (i = 0; i < arr.length; i++) {
yield * fn(arr[i])
}
}
function * value (val) {
yield val
}
function * recursiveGenerator(node) {
yield * node.type === 'root' ? foreach(node.value, recursiveGenerator) : value(node.value)
}
for (var generated of recursiveGenerator(nodes)) {
console.log(generated);
}
So the generator itself becomes a one-liner!