Sketch of Vec, Slice and Array -> Iterator: Helpful? Clear?

It doesn't really matter which is implemented in terms of what. That could be changed tomorrow and nothing would be different from a user's perspective. I just meant they do the same thing.

There is a sense in which IntoIterator is more important, because if IntoIterator didn't exist then you wouldn't be able to use it in generics; whereas if .iter() didn't exist you would just have to use (&foo).into_iter() instead and it would be a little bit more verbose and annoying but not really less expressive in any way. But since both exist it doesn't matter which one is implemented in terms of the other.

Hmm, sorry, I know C pretty well but I'm not really sure what this question means. I think you might be confusing &str with str? They are distinct types. String is a pointer to str, &str is another kind of pointer to str. Vec<T> is similarly a pointer to [T].

The problem (?) with FullFeatured<T> and DataOnly<'_, T> is that FullFeatured<T> is not a pointer to DataOnly<'_, T>. You couldn't implement Deref for FullFeatured so that it points to DataOnly (or vice versa). This doesn't mean they're not useful types, they're just not related to each other the way Vec<T> and [T], or String and str are.

Deref is fundamentally a trait that is implemented for pointers, or things that are in some way pointer-like (there's some disagreement around what exactly should be Deref; here's an earlier thread on that subject). Deref doesn't say anything about serialization or equality or what other data the struct might have... it basically just says "this struct points to something". Vec<T> implements Deref because it's a (smart) pointer, and the thing it points to is [T]. Since it implements Deref, you can use . to call methods of [T] on Vec<T>, the same way you can call methods of [T] on &[T]; they're both pointers.

The author meant IntoIterator.

If Collection<T> can implement IntoIterator, do that. If you can implement IntoIterator for &Collection<T> and/or &mut Collection<T>, with the semantics one would expect, you should do that too. If there are other ways of iterating over your collection, write inherent methods, like Vec<T>::drain (which yields Ts by emptying, not consuming, the Vec).

The other "half" of the interface between collections and iterators, which hasn't been mentioned directly in this thread yet, is FromIterator<T>, which is the trait that enables Iterator::collect. You implement FromIterator<T> for Collection<T> to be able to write things like let c: Collection<T> = some_iterator.collect(). I suppose you could say that FromIterator<T> and IntoIterator are what Rust has instead of a high-level Collection interface like in Java.

DerefMove (if it existed) could take self in the same way DerefMut takes a &mut self; for example:

trait DerefMove: DerefMut {
    type Output;
    fn deref_move(self) -> Self::Output;
}

Box does not need this because the knowledge of how to move things out of a Box is actually coded within the compiler itself. You can call .into_iter() on a Box<Vec<T>>. But this isn't possible for other types.

2 Likes