<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun 9, 2013, at 2:34 AM, Jason Orendorff wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">On Sun, Jun 9, 2013 at 2:17 AM, Axel Rauschmayer <span dir="ltr"><<a href="mailto:axel@rauschma.de" target="_blank">axel@rauschma.de</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
> Another use case for iterator support: retrieve the first element from 
an iterator, then iterate over the remaining elements via for-of.<br><div><br></div><div>Right, this happens whenever you're doing a fold and your combining function has no handy "zero" value. For the sake of concreteness let's say we're writing code for a robot kitchen, and we've got a function for taking a collection of bowls and dumping all the contents into the first bowl. In Python:<br>
<br>    def combine(bowls):<br>        iterator = iter(bowls)<br>        first_bowl = next(iterator, None)<br>        for bowl in iterator:<br>            dump_into(bowl, first_bowl)<br></div><br><div>In JS the same function would be:<br>
</div><div><br></div><div>    from "yet_unspecified_standard_module" import iteratorSymbol;<br></div><div><br>    function combine(bowls) {<br>        let iterator = bowls[iteratorSymbol]();<br>        let {value: firstBowl, done} = iterator.next();<br>
        if (done)<br>            return;  // no bowls at all<br>        let rest = {};<br>        Object.defineProperty(rest, iteratorSymbol, {value: () => iterator});<br>        for (let bowl of rest)<br>            dumpInto(bowl, firstBowl);<br>
    }<br><br></div><div><div>If you don't mind copying the source collection into an array, you can use destructuring instead:<br><br></div><div>    let [?first, ...rest] = bowls;<br><br>At least, I think that's the current proposed destructuring syntax/semantics. Of course this only works if the use case has a structure that the destructuring mini-language can express.<br>
</div></div><div><br></div><div>Other use cases come up too: (1) you want to process a sequence in one loop until you reach some marker, and then break out of the first loop and process the rest in another loop; or (2) you want to pass the iterator to a separate function that consumes a subsequence of the input. (For example, when the input sequence is from a file, and you're doing some light parsing.)<br>
<br></div><div>I think it's a mistake for iterators not to be iterable. We will have error messages like "Iterator object is not iterable", and users will say "*really*, JavaScript?". Requiring users to build pseudo-collection objects like `rest` in these use cases seems awfully bureaucratic, and hard to justify without resorting to types.<br></div></div></div></div></blockquote><div><br></div><div>Iterators can be Iterables and any Iterator created as a generator will automatically be an Iterator.</div><div><br></div><div>But it really comes down to the startup behavior of for-of if the value of the |of| expression is not an Iterable.</div><div><br></div><div>Currently the spec. days that if it is not an Iterable the for-of loop doesn't run (although some of the details in the For In/Of Expression Evaluation looks a little bogus).  It would be easy enough to to spec. it such that if the value is not an Iterable (does not have an @@iterator property) then it just assumes that it must already be an Iterator.</div><div><br></div><div>in that case we could say:</div><div><br></div><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>    function combine(bowls) {<br>        let iterator = bowls[iteratorSymbol]();<br>        let {value: firstBowl, done} = iterator.next();<br>        if (done)<br>            return;  // no bowls at all<br>         for (let bowl of iterator)<br>            dumpInto(bowl, firstBowl);<br>    }<br></div></div></div></div></div><div><br></div><div>Allen</div></div></body></html>