I'm learning Rust and noticed the following iterator pattern in a number of places:
let some_vector: &[& str] = &["hello", "world", "zombies", "pants"];
let result: Vec<&str> = some_vector
.iter()
.filter(|&x| *x == "hello")
.map(|&x| x)
.collect();
What's the purpose of that .map(|&x| x)
? Why is it necessary? Does it create a copy?
When I remove it, I get the following compiler error:
error[E0277]: a value of type `Vec<&str>` cannot be built from an iterator over elements of type `&&str`
--> src/main.rs:7:6
|
7 | .collect();
| ^^^^^^^ value of type `Vec<&str>` cannot be built from `std::iter::Iterator<Item=&&str>`
|
= help: the trait `FromIterator<&&str>` is not implemented for `Vec<&str>`
note: required by a bound in `collect`
For more information about this error, try `rustc --explain E0277`.
So the map
turns an iterator over references to string slices into an iterator over string slices? Removing one level of indirection? Is that right?
In addition to @AlexW's answer, actually there is no need to write that, because there is a builtin iterator adapter that does it better (more clear, more performant): copied()
.
let some_vector: &[&str] = &["hello", "world", "zombies", "pants"];
let result: Vec<&str> = some_vector
.iter()
.filter(|&x| *x == "hello")
.copied()
.collect();
There is also cloned()
which is equal to .map(|x| x.clone())
.
Assuming you're using 2021 edition, it converts from impl Iterator< Item = &&str>
to impl Iterator< Item = &str>
:
let some_vector: &[& str] = &["hello", "world", "zombies", "pants"];
let result: Vec<&str> = some_vector // &[&str]
.iter() // Iter<&str>
.filter(|&x| *x == "hello") // Impl Iterator< Item = &&str>
.map(|&x| x) // Impl Iterator< Item = &str>
.collect();
And the reason it's necessary is because the FromIterator
trait is already implemented for &str
as it's a relatively more common use case and it's not implemented for &&str
as the error message says:
the trait `FromIterator<&&str>` is not implemented for `Vec<&str>`
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With