3

I have a indexable type that I want to iterate over. It consists of some metadata and an array. I need to first iterate over the bytes of the metadata and then to that of the array. From what I understand, the iterator cannot have any storage local to the trait implementation. I think this is very disorganized, and I don't want my data types to be muddled by the need to satisfy extraneous influence.

impl Iterator for IndexableData {
  type Item = u8
  let index : isize = 0;
  fn next(& mut self) -> Option<Item> {
     if self.index > self.len() { None }
     if self.index > size_of::<Metadata> {
       Some (self.data[index - size_of::<Metadata>])
     } 
     Some (self.metadata[index])
  }
}

This is what I think the implementation should look like. The index variable belongs in the iterator trait. Not my IndexableData type. How can I achieve this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Adam Miller
  • 1,756
  • 1
  • 25
  • 44

1 Answers1

7

The Iterator should be a separate struct that has a reference to the collection plus any other data it may need (such as this index). The collection object itself should not be an iterator. That would not only require misplaced additional metadata in the collection, it would prevent you from having multiple independent iterators over the collection.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • This ends up making a lot of interoperation with other traits very wonky. What I mean by that is that, the data of interest is what the programmer starts out with and wants to focus on, but in the process of conforming to the type checker, they end up making all these ancillary structs that hide behind the scenes of what is otherwise an innocuous set of methods that make up the public interface. Programmers aren't interested in making all those other structs because that's fundamentally just noise forced by the language. – Adam Miller Sep 12 '16 at 05:23
  • In addition, that noise has the potential to complicate other tasks when interoperation between traits behind the scenes is required. – Adam Miller Sep 12 '16 at 05:23
  • 1
    @AdamMiller This is not pointless boilerplate enforced to ruin your day. Iterators (in the sense used here) are separate from collections **in every language I am aware of** (though some make it a bit easier to define one-off iterators, like e.g. generators in Python). It is *logically* necessary because, as I said, you want the ability to have multiple iterator over a collection and not carry the baggage of an iterator when that is not required. [For lack of examples I cannot address your points about "other traits".] –  Sep 12 '16 at 09:47
  • I don't disagree - you agree with only half of what I'm addressing. First, it's correct to isolate other data types from the public interfaces and only reveal the consumer api that is as minimalist as possible. But the problem that I'm identifying is that having so many types to wrangle is turning it into a rodeo. To be honest, for lots of interfaces, I don't want the type to ever be used again. It seemed to make sense to me to have trait local private fields, where the compiler would use to auto-derive a struct with. Seems less cumbersome to me, but admittedly only sometimes more intuitive. – Adam Miller Sep 12 '16 at 10:01