Defining and implementing the Iterable trait with GATs
To express traits like Iterable
, we can make use generic associated types -- that is, associated types with generic parameters. Here is the complete Iterable
trait:
Let's walk through it piece by piece...
- We added a
'collection
parameter toItem
. This represents "the specific collection that theItem
is borrowed from" (or, if you prefer, the lifetime for which that collection is borrowed). - The same
'collection
parameter is added toIterator
, indicating the collection that the iterator borrows its items from. - In the
iter
method, the value of'collection
comes fromself
, indicating thatiter
returns anIterator
linked toself
. - Each associated type also has a
where Self: 'collection
bound. These bounds are required by the compiler -- if you don't add them, you will get a compilation error. As explained here, this is a compromise that is part of the GATs MVP to give us time to work out the best long-term solution.- The bound
where Self: 'collection
is called an outlives bound -- it indicates that the data inSelf
must outlive the'collection
lifetime
- The bound
Implementing the trait
Let's write an implementation of this trait. We'll implement it for the Vec<T>
type; a &Vec<T>
can be coerced into a &[T]
slice, so we can re-use the slice Iter
that we defined before (the playground link includes an impl of Iterable
for [T]
as well, but we'll use Vec
here because it's more convenient).
Invoking it
Now that we have the Iterable
trait, we can reference it in our "count twice" function.
and we can invoke that by writing code like count_twice(&vec![1, 2, 3, 4, 5, 6])
.
Play with the code from this section on the Rust playground.