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