-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Add new iterator adapator .filter_scan() #14425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
filter_scan() is like scan() but it skips None values. It also has a method .chain_state() that adds one final iteration value by mapping the state through a closure.
How is this different than The extra value added can't be expressed today, but why was it added for just one iterator and no others? |
@alexcrichton I added
|
As for Another option is to build a separate iterator adaptor that chains a single result by executing a closure on a |
There's a lot of similarity with this approach and my |
Closing due to inactivity, but feel free to reopen again. |
@alexcrichton I still think this is useful. All it's waiting on is a review and/or a comparison with @erickt's FWIW, |
AFAICS you can almost solve your code example using scan and filtermap, but I didn't manage to get the last word, and I don't know how well this will be optimized. fn main() {
let s = "this is a sentence";
let mut it = s.char_indices().scan(0u, |i1, (i2, c)| {
if c.is_whitespace() {
let word = s.slice(*i1, i2);
*i1 = i2+1;
Some(Some(word))
} else {
Some(None)
}
}).filter_map(|x| x);
assert_eq!(it.next(), Some("this"));
assert_eq!(it.next(), Some("is"));
assert_eq!(it.next(), Some("a"));
// assert_eq!(it.next(), Some("sentence")); # NOT WORKING
assert_eq!(it.next(), None);
} Perhaps chain_state could be renamed to finally and added as a method to the normal ScanIterator. Then the code example could be changed into something like the following let mut it = s.char_indices()
.scan(0u, |i1, (i2, c)| {
.... // Same code as above
})
// last word
.finally(|i1, (i2, _)| Some(Some( s.slice(*i1, i2+1))))
.filter_map(|x| x); Alternatively you can add a whitespace at the end of the string, but that feels like a hack. EDIT: Ideally a Peekable iterator should allow you to peek ahead inside a for-loop. That would would solve the problem of getting the last word. Perhaps i2 could have a method named peek(), but also coerce to uint. |
Closing. Between this PR and #14271, this subject has been closed several times with little agreement. Please agree on a design and convince others that it is needed. |
This PR supersedes rust-lang#14328 following the [2025-03-18 Clippy meeting discussion](https://rust-lang.zulipchat.com/#narrow/channel/257328-clippy/topic/Meeting.202025-03-18/with/506527762). It uses a simpler approach than what was proposed initially in rust-lang#14328 and does not add new options. First, it documents how `cfg_attr` can be used to change the MSRV considered by Clippy to trigger the lint. This allows the MSRV to be feature gated, or to be raised in tests. Also, the lint stops warning about items which have been explicitly allowed through a rustc feature. This works even if the feature has been stabilized since. It allows using an older compiler with some features turned on, as is done in Rust for Linux. This fixes rust-lang#14425. Then, if the lint triggers, and it looks like the code is located below a `cfg` or `cfg_attr` attribute, an additional note is issued, once, to indicate that the `clippy::msrv` attribute can be controlled by an attribute. Finally, the lint is extended to cover any path, not just method and function calls. For example, enumeration variants, or constants, were not MSRV checked. This required replacing two `u32::MAX` by `u32::max_value()` in MSRV-limited tests. An extra commit adds a TODO for checking the const stability also, as this is not done right now. @Centri3 I'll assign this to you because you were assigned rust-lang#14328 and you were the one who nominated the issue for discussion (thanks!), but of course feel free to reroll! r? @Centri3 changelog: [`incompatible_msrv`]: better documentation, honor the `features` attribute, and lint non-function entities as well
filter_scan() is like scan() but it skips None values. It also has a
method .chain_state() that adds one final iteration value by mapping the
state through a closure.