We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Closures and Iterators step 24 of 28
Make your own collection iterable, all three ways
Add borrowed iteration to Bag, a wrapper around Vec<i64>. Keep the supplied
roundtrip function and the two enabled Clippy lints unchanged.
The starter already implements FromIterator<i64>, Extend<i64> and consuming
IntoIterator for Bag. Add these four pieces:
IntoIterator for &Bag, yielding shared references.IntoIterator for &mut Bag, yielding mutable references.- An inherent
iter(&self)method. - An inherent
iter_mut(&mut self)method.
Delegate to the inner vector and its slice iterators. You do not need a custom iterator type or a copy of the vector for borrowed iteration.
What roundtrip does
pub fn roundtrip(items: Vec<i64>) -> (Vec<i64>, i64, Vec<i64>)
It collects the input values into a Bag, sums them through shared iteration,
doubles them through mutable iteration, and copies the doubled values into a
snapshot. It then appends the original input and consumes the bag.
The return order is (doubled, original_sum, consumed). For [1, 2, 3],
that is ([2, 4, 6], 6, [2, 4, 6, 1, 2, 3]). Empty input produces
([], 0, []). Preserve element order and duplicates. Test inputs keep
doubling and the running sum within i64 range.
Each loop uses a different receiver type
| Loop | Trait implementation | Yielded item | Effect on the bag |
|---|---|---|---|
for x in &bag |
IntoIterator for &Bag |
&i64 |
Borrows its contents for reading |
for x in &mut bag |
IntoIterator for &mut Bag |
&mut i64 |
Borrows its contents for mutation |
for x in bag |
IntoIterator for Bag |
i64 |
Consumes the bag |
A for loop uses IntoIterator to obtain an iterator. Implementing the trait
for Bag does not generate implementations for either reference type. That
is why the starter fails at the borrowed loops even though consuming iteration
is already implemented.
Connect the borrowed items to their lifetime
The shared implementation uses these associated types:
impl<'a> IntoIterator for &'a Bag {
type Item = &'a i64;
type IntoIter = std::slice::Iter<'a, i64>;
fn into_iter(self) -> Self::IntoIter {
self.items.iter()
}
}
Here, Self is &'a Bag. The self parameter already is a reference; changing
the receiver to &self would give the wrong trait signature. The named lifetime
connects that borrow to both the iterator and the references it yields.
For mutable iteration, use &'a mut Bag, &'a mut i64 and
std::slice::IterMut<'a, i64>, delegating to self.items.iter_mut(). The borrow
checker prevents conflicting access while the mutable borrow is still in use.
Consuming iteration already returns std::vec::IntoIter<i64>.
Naming these existing iterator types also preserves their capabilities, such
as exact remaining length and iteration from the back. Bag itself does not
need to implement Iterator.
Provide the matching methods
Add these inherent method signatures and delegate their bodies to the vector:
pub fn iter(&self) -> std::slice::Iter<'_, i64>
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, i64>
The placeholder lifetime '_ works in these method return types because it is
inferred from the receiver borrow. In the trait implementations above, name
the lifetime so the associated types can refer to it.
iter and iter_mut are conventional method names. Providing those methods
alone does not make the borrowed for loops work; the trait implementations
are also needed. This exercise enables both directions of Clippy's convention
checks:
#![deny(clippy::into_iter_without_iter, clippy::iter_without_into_iter)]
Retain that attribute. The solution must compile, return the expected values, and pass Clippy with warnings treated as errors.
Collection building is already implemented
FromIterator<i64> lets collect() produce a Bag; Extend<i64> appends
values to an existing one. Both methods accept an IntoIterator, so callers
can supply a collection or an iterator. Their existing implementations simply
delegate to Vec and need no changes for this task.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.