After some discussion with strcat on IRC, I believe we should try to
switch to external iterators. It is true that they can be somewhat
harder to write, but the advantages are numerous:

- Easy integration with static analyses, without need for new keywords
  and so forth:
  - Borrow checker need not be conservative against incorrectly implemented
    iterators, so `return &mut foo` will work.
  - Fold can be implemented safely without moving from an upvar:
    `let a = a0; for v.each |i| { a = op(a, i); }; a` (today this yields an
    error as `op(a, i)` moves from the upvar `a` unless you supply a Copy 
bound).
  - Various bits of code and logic are simplified by not having to transform
    the `for` loop closure.

- Potentially faster compile times, less reliance on inlining and fewer
  #[inline(always)] declarations. With an inline iterator, if we don't
  inline, performance drops off a cliff (virtual call for every element).
  This is not true for an external iterator.

- We can have `return` just make "early return from the innermost closure"
  as many people have requested. It'd be quite consistent.

- Internal closures can still be implemented using `do` if truly desired.

I imagine that `for <expr> |<pat>| { <body> }` would be syntactic sugar
for:

    let mut _iterator_ = <expr>;
    loop {
        let <pat> = match _iterator_.next() {
            None => break,
            Some(v) => v
        };
        <body>
    } 

or something similar, depending on the precise iterator protocol that
we adopt. If `|<pat>|` is omitted it would be equivalent to `|()|`.

Arguably retaining the current `for` syntax suggests closures where
none exist, but it seems silly to change it and invalidate all
existing programs for this reason (I imagine `for <pat> in <expr>`
would be the more standard syntax).


Niko

On Thu, Jun 06, 2013 at 11:25:28AM -0700, Graydon Hoare wrote:
> On 05/06/2013 9:15 PM, Patrick Walton wrote:
> >On 6/5/13 9:09 PM, Daniel Micay wrote:
> >>I think extending the built-in `for` loop to work with external iterators
> >>should be considered, because right now the verbosity discourages
> >>using them
> >>and makes borrow checking more painful than it has to be.
> >>
> >>It could treat functions as internal iterators, and look for an
> >>`Iterator`
> >>implementation (using a `lang` item) for external ones.
> >>
> >>Python's `for` loop starts by looking for an iterator (a `__next__`
> >>method) and
> >>falls back to an iterable (an `__iter__` method) so behaviour like
> >>this isn't
> >>an alien concept.
> >
> >This is a very well-thought out post, and I find it persuasive. The
> >mutability issue is one I hadn't considered, and seems to make a good
> >argument for including both in the language.
> 
> Yeah. I think it's clear enough that both have their (strong)
> advantages; we have hashmaps and treemaps too, and both vectors and
> lists :)
> 
> The main thing I'm concerned with is making the interfaces to user
> code smooth enough that neither feels markedly second-class or
> unusable. Extending 'for' as you suggest sounds like a good step.
> 
> It might also be good to add a tutorial chapter on the matter,
> introducing these terms and relating them together, so users can see
> the relative use cases.
> 
> Thanks for the ongoing work in this area!
> 
> -Graydon
> 
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to