Cargo clippy: this `.filter_map` can be written more simply using `.filter`

I have some code like this:

    let extensions: Vec<&vk_parse::Extension> = extensions
        .iter()
        .filter_map(|extension| {
            if let Some(supported) = &extension.supported {
                if supported.as_str() == "disabled" {
                    return None;
                }
            }
            Some(extension)
        })
        .collect();

When I use cargo clippy to check my code, it suggested that:

warning: this `.filter_map` can be written more simply using `.filter`
  --> generator/src/generate_extensions.rs:34:49
   |
34 |       let extensions: Vec<&vk_parse::Extension> = extensions
   |  _________________________________________________^
35 | |         .iter()
36 | |         .filter_map(|extension| {
37 | |             if let Some(supported) = &extension.supported {
...  |
42 | |             Some(extension)
43 | |         })
   | |__________^
   |
   = note: `#[warn(clippy::unnecessary_filter_map)]` on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map

But IICR the if let chain feature is still on RFC state, I don't know how to convert this:

            if let Some(supported) = &extension.supported {
                if supported.as_str() == "disabled" {
                    return None;
                }
            }
            Some(extension)

into a single comparison statement.

I know that cargo clippy is not that clever in some cases, but I still wondered if there's a way to use filter rather than filter_map

I mean, if nothing else you could write this:

let extensions: Vec<&vk_parse::Extension> = extensions
        .iter()
        .filter(|extension| {
            if let Some(supported) = &extension.supported {
                if supported.as_str() == "disabled" {
                    return false;
                }
            }
            true
        })
        .collect();

If you do want a single statement, you can do this:

let extensions: Vec<&vk_parse::Extension> = extensions
        .iter()
        .filter(|extension| {
            extension.supported.as_deref().map(|supported| supported == "disabled").unwrap_or(false)
        })
        .collect();
2 Likes

Maybe you could do something like !matches!(extension.supported, Some("disabled")) ?

(though, I dislike that double exclamation mark)

2 Likes

The double "!" indeed confused me at first glance :rofl:

a good solution is to add extra parentheses

!(matches!(extension.supported, Some("disabled")))
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.