4 ms·
The code here repeatedly defines functions which return an object with only one property, with the name being Symbol.iterator and the value being a generator fu
by voyou 12y ago
The code here repeatedly defines functions which return an object with only one property, with the name being Symbol.iterator and the value being a generator function. Is there a reason to do this, rather than just writing a generator function directly?
- inglor 12y agoWell, you can't iterate a generator without invoking it. If you returned a generator you can't `for(let x of myGeneratorFn)` because it's not an iterable - rather a generator is just sugar for a function that returns an iterable. You'd have to do `for(let x of myGeneratorFn())` although in this case I agree it's silly to return it like this.
- scotty79 12y agoHe couldn't return generator instance because he needs two instances of game running at the same time for the tortoise and hare algorithm to run in const memory. He would need to return at least generator function but that would force him to invoke it before iterating.
- deleted 12y ago[deleted]
- inglor 12y agoNo you don't, you can Do `Array.from(myGeneratorFn())` or `[...myGeneratorFn()]` just fine - the difference is that you have to invoke it - you certainly _don't_ have to call .next to extract elements all the time manually.
- picks_at_nits 12y agoVery true, You have to decide at some point whether you’re going to have everything be callable, or everything be an object, and thereafter be consistent. The functions `takeIterable` and `statefulMapIterableWith` are both written to take and return iterables, but you could write parallel versions operating directly on callables. You probably want them to return the same thing they consume. A more full-featured utility might pattern match on what it is given and return the same form.
- voyou 12y agoSure, but it's takeIterable and statefulMapIterableWith which I was wondering about. They are themselves callables which return iterables. Is there any reason not to write them as generator functions?
- picks_at_nits 12y agoThese would have been excellent questions for Christine to ask! I made an es6 fiddle: http://www.es6fiddle.net/i6fralh4/ http://www.es6fiddle.net/i6fralh4/ Is this what you mean? --- const takeIterable = (numberToTake, iterable) => ({ [Symbol.iterator]: function* () { let remainingElements = numberToTake; for (let element of iterable) { if (remainingElements-- <= 0) break; yield element; } } }); const x = takeIterable(3, [1, 2, 3, 4, 5]); console.log(...x); console.log(...x); console.log(...x); //=> [1, 2, 3] [1, 2, 3] [1, 2, 3] function* takeGenerator (numberToTake, iterable) { let remainingElements = numberToTake; for (let element of iterable) { if (remainingElements-- <= 0) break; yield element; } }; const y = takeGenerator(3, ["a", "b", "c", "d", "e"]); console.log(...y); console.log(...y); console.log(...y); //=> [“a”, “b”, “c”] [] []
- voyou 12y agoAh, the penny drops. Thanks. I've actually been bitten by not paying attention to the same distinction in python, which I evidently haven't quite learned the lesson of yet.
- jessaustin 12y agoThat's great; you've really made this clear. In python, one would just use itertools.tee() to get multiple bites at a particular iterator, rather than relying on sugary syntax to instantiate the iterator multiple times; perhaps ES6 should have something similar? I have to say, this "Symbol.iterator" magic string seems like an even less felicitous way to write this than python's dunderous __iter__() function. Maybe coffeescript or one of its forks can help ES explore a more reasonable way to write this.