Skip to content

needless_join for Iter<String> #8570

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

Closed
yoav-lavi opened this issue Mar 21, 2022 · 0 comments · Fixed by #8579
Closed

needless_join for Iter<String> #8570

yoav-lavi opened this issue Mar 21, 2022 · 0 comments · Fixed by #8579
Labels
A-lint Area: New lints

Comments

@yoav-lavi
Copy link
Contributor

yoav-lavi commented Mar 21, 2022

What it does

When transforming an Iter<String> to String, you can either use:

.collect::<Vec<String>>().join(""):

let vector = vec!["hello",  "world"];
let output = vector.iter().map(|item| item.to_uppercase()).collect::<Vec<String>>().join("");
println!("{}", output);

or

.collect::<String>():

let vector = vec!["hello",  "world"];
let output = vector.iter().map(|item| item.to_uppercase()).collect::<String>();
println!("{}", output);

The latter being terser and more performant:

fn criterion_benchmark(criterion: &mut Criterion) {
    criterion.bench_function("1", |bencher| {
        bencher.iter(|| {
            vec!["hello", "world"]
                .iter()
                .map(|item| item.to_uppercase())
                .collect::<Vec<String>>()
                .join("")
        })
    });
    criterion.bench_function("2", |bencher| {
        bencher.iter(|| {
            vec!["hello", "world"]
                .iter()
                .map(|item| item.to_uppercase())
                .collect::<String>()
        })
    });
}
1                       time:   [155.79 ns 155.97 ns 156.16 ns]                   
Found 4 outliers among 100 measurements (4.00%)
  2 (2.00%) high mild
  2 (2.00%) high severe
slope  [155.79 ns 156.16 ns] R^2            [0.9971885 0.9971738]
mean   [155.87 ns 156.58 ns] std. dev.      [672.36 ps 2.9345 ns]
median [156.12 ns 156.26 ns] med. abs. dev. [209.02 ps 650.40 ps]

2                       time:   [118.11 ns 118.20 ns 118.28 ns]                   
Found 8 outliers among 100 measurements (8.00%)
  8 (8.00%) high severe
slope  [118.11 ns 118.28 ns] R^2            [0.9987699 0.9987697]
mean   [118.31 ns 118.87 ns] std. dev.      [794.06 ps 2.0461 ns]
median [117.96 ns 118.43 ns] med. abs. dev. [154.11 ps 692.31 ps]

I suggest adding a new lint called needless_join that detects the case of .collect<Vec<String>>.join("") on a String iterator.

Thank you for your consideration!

Lint Name

needless_join

Category

perf

Advantage

  • It is shorter
  • It is more performant
  • The intent is clearer

Drawbacks

None that I'm aware of

Example

let vector = vec!["hello",  "world"];
let output = vector.iter().map(|item| item.to_uppercase()).collect::<Vec<String>>().join("");
println!("{}", output);

Could be written as:

let vector = vec!["hello",  "world"];
let output = vector.iter().map(|item| item.to_uppercase()).collect::<String>();
println!("{}", output);

See cases of this happening in the wild here (GitHub CS Beta) or here (Sourcegraph)

I'm learning Rust so please let me know if I'm missing something!

@yoav-lavi yoav-lavi added the A-lint Area: New lints label Mar 21, 2022
@yoav-lavi yoav-lavi changed the title needless_join for String / &str Iters needless_join for String Iter`s Mar 21, 2022
@yoav-lavi yoav-lavi changed the title needless_join for String Iter`s needless_join for Iter<String> Mar 21, 2022
@bors bors closed this as completed in e29b3b5 Mar 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant