Why do Iterator methods use `usize`?


#1

I would expect them to use u32 or u64, since they aren’t necessarily tied to a datastructure of usize elements (like Vec). Should I file an issue?

Some examples:

fn size_hint(&self) -> (usize, Option<usize>) { ... }
fn nth(&mut self, n: usize) -> Option<Self::Item> { ... }
fn skip(self, n: usize) -> Skip<Self> { ... }
fn take(self, n: usize) -> Take<Self> { ... }
fn position<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool { ... }
fn rposition<P>(&mut self, predicate: P) -> Option<usize> where Self: ExactSizeIterator + DoubleEndedIterator, P: FnMut(Self::Item) -> bool { ... }

#2

You’d have to file it in the RFC repo, since it’s a major API change – and we’re past the beta, so it really has to be an emergency to go through :smile:

I’ll explain why it’s not a very big deal.

The core API is this:

fn next(&mut self) -> Option<Self::Item>

It has no assumption about length and can deliver elements infinitely. So infinite or longer than current usize::MAX iterators are supported.

size_hint has one primary purpose: to size allocations well when creating collections from iterators. In general, these are limited by usize too, so the types match well. Of course it does not match with sizing other kinds of resources, for example files. Fortunately it’s just a hint. The protocol specifies you should use usize::MAX as the bound if it is known to be larger than usize (including infinite).

The other methods, nth, skip, take, position are all un/fortunately O(index) complexity methods, which means that in practice you really want to avoid using big numbers here. Position is frequently useful with vecs/slices, which use usize indices.

I can see that it looks limiting… In the worst case though, they are just adaptors and library code can create their own, maybe there is a use case for .take64(n: u64) or even bigger!


#3

It’s basically completely arbitrary, but it does serve a few use cases, where it’s referencing a container that contains a non-zero-sized structure that lives in the RAM.


#4

Iterators aren’t backed by a specific data structure, but they certainly can by implemented by specific data structures. Those data structures might require usize.


#5

But you can as well say: Iterators aren’t backed by specific data structures, but they can be implemented by data structures that require {u32, u64, etc.}.


#6

It occurred to me that the nth, skip, take adaptors are overridable now again. I still think that doesn’t make them very viable for random access since the structs they must return are fixed. Maybe a future mature random access api can be formed and the question of type for the offsets will come up again.