I’ve been learning ES6 for a few weeks now, recording my efforts as live screencasts for my WatchMeCode series on ES6 in the process. In episode 91, as I am stumbling my way through learning how generators work, I decided to try a recursive call for a generator function just to see what happens.
I found the result to be rather interesting. I had created an infinitely nested / recursive call stack in my code, but the use of generators allowed me to control just how deep the recursion went by limiting the number of times I allowed the code to execute. And it did all of this from outside of the recursive function!
This had me wondering what it would look like to build a nested data structure and use generators to traverse it. So I did! And here’s what I came up with.
The Data Structure
The data structure is fairly simple just for demo purposes. I have an “id” field and a list of “children”. The id is formatted so I can see which level / item I am currently looking at. The children are stored in an array of items that have the same structure.
The Recursive Function
The generator function I wrote to do the recursion isn’t super complicated. If you’ve ever done recursion on a nested data structure, it should look familiar: grab the current item, look for children and iterate the children if there are any.
In this case, the use of the data found in the tree is not handled with a callback or event as I’ve done in the past. Instead, I’m yielding the data out of the generator.
Also note that on line 9, I’m yielding the recursive generator function call using the *fn() syntax format. This tells the generator to give control to the iterator produced by this function. In other words, this is what allows the nested / recursive generator function to work with a single iterator object from the outside.
Traversing The Tree
With the recursive generator function in place, I only needed to get the iterator and call it. There are several ways of doing this, but I chose to use a “while” loop using the iterator.next() call:
The output is exactly what I was looking for – depth-first traversal of the tree structure.
There are still other ways to traverse this, by manually calling iterator.next() at various points. The important point here, is that you can easily traverse the entire data structure with the iterator.next() calls – limiting the traversal to a specific number, or attempting to iterate the entire tree using a while loop.
Is There Any Real Use For This?
Other than the “cool” factor of using ES6 generators for recursion, I find myself wondering if there’s any real application of this idea. Are there benefits of doing this in comparison to standard / traditional / older forms of recursion? Does the external control of when the iteration happens provide a huge benefit in any way? Or is this just another fun exercise to see what can be done, with no practical application?
I’d love to hear your thoughts about the usefulness of this pattern!