The current documentation for std::iter::Iterator::zip is unclear about the order in which the two iterators are queried:
Creates an iterator that iterates over both this and the specified iterators simultaneously, yielding the two elements as pairs. When either iterator returns None, all further invocations of next() will return None.
If I had to guess from this documentation, I’d say that Zip's next calls next on both its iterators, then returns None if either is None. In fact, it only queries the second iterator if the first is Some(_):
#[inline]
fn next(&mut self) -> Option<(A::Item, B::Item)> {
match self.a.next() {
None => None,
Some(x) => match self.b.next() {
None => None,
Some(y) => Some((x, y))
}
}
}
Is this behavior intentionally unspecified?
The order can matter if the sequences being zipped are unbalanced in length. Currently, if the first sequence is longer, then the Zip iterator discards an item each time its next is called. If the second sequence is longer, no items are discarded.
core::fmt::write exploits this behavior by iterating over arguments zipped with string pieces. When the zipped iteration completes, it retrieves the trailing piece using the underlying piece iterator. I did a quick scan of the standard library, but I wasn’t able to find any other obvious instances.