JavaScript Generators, Meet XPath
jack.wrenn.fyi
jack.wrenn.fyi
- Instead of modifying prototype, which would pollute the environment for any other modules to work with - use regular old functions
- Instead of spreading the iterable to an array and then calling `.forEach` on it, I would just iterate the source generator directly, it would look like:
for (const node of xpath(el, 'xpath')) {
node.textContent = node.textContent.replace("Hello", "Greetings")
}Not necessarily, that's an implementation detail. The result of an XPath query is not an array, it's some object that accepts integer indices for lookup.
If you were to return an array, there would be no way to break out of iteration early without paying for every lookup. For something like XPath, breaking out early is a likely scenario.
Additionally composability seems improved, due to all functions being able to be written in a way where they themselves become generators, so you apply all steps only to each result you retrieve. Potentially saving quite a bit of execution time, if you don't need the full collection.
[...document.xpath("//text()[contains(., 'Hello')]")]
.forEach(node => node.textContent = node.textContent.replace("Hello", "Greetings"));
versus for (const node of document.xpath("//text()[contains(., 'Hello')]"){
node.textContent = node.textContent.replace("Hello", "Greetings");
}
No allocation of a pointless array, no redundant iteration, fewer "[]", "()" and no "=>" or "...". No downside whatsoever!That's not entirely true if you need to support IE, in which case Babel (or whatever compiler you're using) will generate extra code for the `for...of` loop. But even then, I would still recommend using it for the reasons you mentioned.
xpath("//text()[contains(., 'Hello')]").forEach(...)Your mileage will vary.
> One caveat of spreading iterables: JavaScript creates an array out of the elements of the iterable. That might be very wasteful for extremely large collections. For example, if we spread a large collection just to find an element in the collection, it might have been wiser to iterate over the element using its iterator directly.
> And if we have an infinite collection, spreading is going to fail outright.
http://raganwald.com/2015/02/17/lazy-iteratables-in-javascri...
It really depends on the logic written. You can solve the same thing in many different ways, the way chosen by the author doesn't seem to be a lazy one.
Not the language's fault. It's simply doing what is asked of it.
If they spread anyway, they could leave the generator away in the first place.