Description
Here is the existing type signature for std::iter::scan:
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> where F: FnMut(&mut St, Self::Item) -> Option<B>,
If I were to use a verbose name for scan
as implemented now, I would call it map_with_state_until
, this means that if I just want map_with_state
, things can get really awkward using the existing scan if I want to return an option which doesn't terminate the Iterator for collect
etc. e.g. vecter.iter().scan( |state, x| if x > 1 then Some(None) else Some(Some(x)) ).flatten()
If we instead have F
just turn B
instead of Option<B>
like:
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> where F: FnMut(&mut St, Self::Item) -> B,
then that becomes a lot more simple:
vecter.iter().scan( |state, x| if x > 1 then None else Some(x) )
and achieving the existing scan
behavior is trivially achieved by simply adding fuse()
.
This allows scan
to have behavior more in-line with similar functions like map
and fold
:
fn fold<B, F>(self, init: B, f: F) -> B where
F: FnMut(B, Self::Item) -> B,
fn map<B, F>(self, f: F) -> Map<Self, F> where
F: FnMut(Self::Item) -> B,
and also brings it more in-line with how other languages define scan
: (a -> b -> a) -> a -> [b] -> [a]
(Haskell), ('State -> 'T -> 'State) -> 'State -> seq<'T> -> seq<'State>
(F#) etc.
I think this also gives a clear way forward to addressing other issues which previously ended up unresolved like:
#14425
So I think there ought to be scan
as defined above, and scan_until
which is the existing implementation.
References:
http://zvon.org/other/haskell/Outputprelude/scanl_f.html