Open G-M0N3Y-2503 opened 3 months ago
After playing around with a peeking_map()
with subsequent adapters, I found that subsequent adapters would require the burden of maintaining the knowledge of whether a value was taken or not, which may vary depending on Output
. It could probably be made nicer with a try_next()
but that would introduce branches for all the subsequent adapters.
The only real way to manage actual short-circuiting that I can see would be within a single code block. So regarding iterators that would be the try_fold
.
However, there are a handful of issues with the current peeking_fold_while
:
std::ops::Try
which would allow for non-eronious short-circuiting, though this is just for readability. PutBack<I>
by unnecessarily constraining it to an immutable reference, where the owned value could be necessary for some.Peekable<I>
currently discards this.I would like to add peeking_skip_while
.
My use case: finding the last item smaller then x and the first item larger then x such that I can generate an interpolated item.
With peeking_skip_while
that would look like this:
data.iter()
.peekable()
.peeking_skip_while(|(x, _)| *x < pos)
.next_tuple() // yields x1, x2 where x1 < x > x2
.ok_or(TooInaccurate)
.inspect(|v| eprintln!("v: {v:?}, pos: {pos}"))
.map(|((a, ay), (b, by))| if pos - a < b - pos { (a, ay) } else { (b, by) })
.and_then(|(x, y)| {
if (pos - x).abs() <= max_deviation {
Ok(*y)
} else {
Err(TooInaccurate)
}
})
Note: I am primarily seeking feedback rather than proposing at this stage.
Peekable
As I see it
peekable
(Existing in std) facilitates two concepts, the ability to preview an item in an iterator and to optionally consume said item. Though it's not a limitation, consumption typically occurs after and/or with some information from a previewed item (&Self::Item
). It is also notable that these only hold true at the point of thePeekable
adapter, that is to say, at the point of a previous adapter, at least one of thepeek
ed forPeekable
and more forPeekingNext
(Existing Trait) items will have been consumed.Existing Extensions
The
peeking_take_while
(Existing in itertools) and similartake_while_ref
(Existing in itertools) consume depending on a predicate with the information from the previewed item (&Self::Item
), thoughtake_while_ref
isn't technically peeking. For the output of these adapters, they output the owned item (Self::Item
) when it has beenaccept
ed via the predicate otherwise none. Generally, the iterator will continue not to output items, as the predicate is fixed at the creation of the iterator, unless interior mutability is used.Remaining Problem Space
As I see it, the problem space doesn't have good solutions for the following (conceptually accumulating) examples.
map
ing with information from or computed with the previewed item (&Self::Item
).accept
ed items remain, liketry_for_each
but withPeekable
.peeking_take_while
adapter can only be reused when you don't need any of the unaccept
ed items.peekable
once for thepeeking_take_while
adapter and again for the following.peek()
.Potential Peekable Adapters
With this in mind, the most general solution for the entire problem space might look something like the following:
with the above examples then looking like this:
and the
peeking_take_while
could then be emulated by this:Related sources
peekable
(Existing in std)peek_map
peeking_take_while
(Existing in itertools)hacked together compile only implimentation
```rust pub struct PeekingMap<'a, I, F> where I: Iterator + 'a, { iter: Peekable<&'a mut I>, f: F, } impl<'a, I, Accept, Map, Output> Iterator for PeekingMap<'a, I, Accept> where I: Iterator, Map: FnOnce(I::Item) -> Output, Accept: FnMut(&mut I::Item) -> ControlFlow