Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Iterable traits #397

Closed
rust-highfive opened this issue Oct 14, 2014 · 7 comments
Closed

add Iterable traits #397

rust-highfive opened this issue Oct 14, 2014 · 7 comments

Comments

@rust-highfive
Copy link

Issue by thestinger
Friday Jul 05, 2013 at 02:59 GMT

For earlier discussion, see rust-lang/rust#7597

This issue was labelled with: A-libs, A-traits, I-enhancement in the Rust repository


Something like the following:

trait Iterable<'self, A, T: Iterator<&'self A>> {
    fn iter(&'self self) -> T;
}

trait ReverseIterable<'self, A, T: Iterator<&'self A>> {
    fn rev_iter(&'self self) -> T;
}

trait MutableIterable<'self, A, T: Iterator<&'self mut A>> {
    fn mut_iter(&'self mut self) -> T;
}

trait MutableReverseIterable<'self, A, T: Iterator<&'self mut A>> {
    fn mut_rev_iter(&'self mut self) -> T;
}

In the future we can define default methods like enumerate when method resolve is fixed. #5898

@alexcrichton
Copy link
Member

I believe this was basically done with IntoIterator, so closing.

@Lucretiel
Copy link

That's untrue. IntoIterator lets you convert self into an Iterator, but there's currently no trait that allows you to convert &self into an iterator.

@sfackler
Copy link
Member

@Lucretiel an implementation of IntoIterator for &T allows a reference to T to be converted into an iterator.

@burdges
Copy link

burdges commented Sep 17, 2018

It's trickier than that since you must use IntoIterator for &T or IntoIterator for &mut T via bounds like for<'a> &'a T: IntoIterator or for<'a> &'a mut T: IntoIterator, but right now compiler bugs prevent doing so. We need the HRTB to permit reborrowing but it makes trait bounds on associates types invisible.

@burdges
Copy link

burdges commented Sep 17, 2018

In this vein, another powerful option would be adding FnBorrow traits for closures whose arguments or return types depend on the lifetime of self, enabling closures that work like Borrow traits. In that example, you'd write batch_normalization(|| v.inter_mut()) and

fn batch_normalization<F>(f: F)
  where F: FnBorrowMut() -> Iterator<&'borrow mut Self>+DoubleEndedIterator+ExactSizeIterator

@Lucretiel
Copy link

If that's the idiom for "iterate over references", it might be worth adding implementations of IntoIterator for the various Iterators and adapters. For instance:

impl<'a, I> IntoIterator for &'a iter::Take<I>
where for <'b> &'b I: IntoIterator { ... }

This came up for me today because I'm trying to find the best way to express "Iterate over an &Collection" for a project I'm working on. My current solution is to use Iterator + Clone, because many Iterators (like slice::Iter) are cheaply cloneable, but I wanted something that promotes a more pit-of-success design.

@burdges
Copy link

burdges commented Sep 17, 2018

Iterator + Clone only works with iterators without mutable results, so nifty but not exactly the answer.

We already have such impls for the basic collection iterators, but you cannot constrain IntoIterator::IntoIter until that compiler bug gets fixed, and thus you cannot .rev() right now.

You cannot do iterator adapters like that regardless because they consume the iterator by value. I think wrapper types should work now, albeit with boiler plate.

I do not know any clean long term solution except expanding closures via roughly the FnBorrow* traits, which solves the iterator adapters issue by making the wrapper type but without the boiler plate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants