I am working on a project, which I was hopping to structure entirely based as combined/chained iterators. However it turned out that one of the most-inner iterators is doing IO, so I have to deal with Result. I started with Iterator<Item=Result<T>>, but I was just hitting problems one by one. It's just not what I want. Eventually it occurred to me that what I really would want is something like an iterator that explicitly handles failure. I thought I should name it "failable iterator". I decided to do a quick crates.io search an indeed someone else (sfackler & contributors) must have had the same idea
So I wonder what do other people think about it. I haven't used it yet, but it seems very necessary for handling any IO in a iterator-based API. Does anyone have better approaches? Would this be something that we could RFC and try to add to standard library, or at least had a chance to become a well recognized and supported primitive?
I think that an approach adding additional methods to Iterator types that handle Results would make more sense as it makes inter-op easier with libraries that aren't compatible with fallible_iterator (such as Rust standard library). For instance, itertools crate crate adds additional methods that handle results such as map_ok.
note that there's a big difference in meaning
between iterator returning Option<Result<Item>> and something that returns Result<Option<Item>>. Iterating over something IO-sourced is not just a sequence of items or errors. It's a sequence of items, that can fail altogether.
Would be great of the normal Iterator unified with that FailableIterator better, but I don't think this is going to work now. Iterator would have to be defined as a special case of FailableIterator that can not fail or something.
My current plan RN is just go take the downsides, and invest into building pieces that I'd need to use FailableIterator.
I agree that Iterator is not the right trait for the pattern you're describing, and that (&mut self) -> Result<Option<T>, Error>, as opposed to ... -> Option<Result<T, Error>>, is the right signature. I don't know whether it's worth pulling in a crate just to have a different trait with a more appropriate contract to implement. My experience with this kind of thing is implementing an incremental parser, where I had lots of types like PageElements that acted like fallible iterators ("parse the next Element, returning Ok(None) if there are no more elements or Err(_) on a parse error"). I ended up going with a normal method fn parse_next(&mut self) -> Result<Option<T>, Error> and chose not to use the fallible_iterator crate.
By the way, it's worth noting that if your problem is getting Option<Result> rather than Result<Option>, Option has a method called transpose which converts Option<Result<T, E>> into Result<Option<T>, E>.