Recipe
Make your own type an iterator
Use when: a sequence can be produced one value at a time from a small amount of remembered state, and you'd rather not build all of it in a Vec
Goal: a struct that implements Iterator, so for loops and every adapter and consumer work on it
Taught in Writing your own iterator
-
1
List what
nextneeds to know to produce the following item: a counter, the next value, a position in a list you own.Example
Hailstone needs only the next number, or "finished":
current: Option<u64>.Why:
nextgets only&mut self, so anything it needs between calls has to live in the struct. -
2
Decide what each call hands out, and write
type Item = ...;in the impl.Example
type Item = u64;for Hailstone;type Item = String;for Turns, which hands out copies of names.Why: the trait requires it (E0046 without it), and every adapter uses it to type its own items.
-
3
Return
Nonewhen the sequence is over. Otherwise work out the value to hand out, update the state for the following call, and returnSome(value).- the state is an Option — start with
let n = self.current?;to returnNoneonce finished. - the sequence never ends — never return
None, and let the caller stop withtake,find, ortake_while.
Why:
nextis the one required method. Every other method calls it. - the state is an Option — start with
-
4
Write
fn new(...) -> Selfthat sets the starting state.Why: callers then can't build a half-set-up iterator, and the state fields can stay private.
Common mistakes
- Forgetting
type Item, which is E0046. - Returning the updated state instead of the current value, which skips the first item.
- Never storing "finished", so the last item repeats forever.