Reputation: 1551
In the below code, I understand that a borrow has been done by the call of zipped.filter
. What I don't understand is how to fix it, if I want to use zipped
again later.
I'm new to Rust, so if there are other problems or strange misuse of idioms in this code, I'm interested in that as well, but primarily about how to make the borrow work twice here.
Code:
fn main() {
let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];
for s1 in &data {
for s2 in &data {
let zipped = s2.chars().zip(s1.chars());
// Did a diff of the two strings have only one character different?
if zipped.filter(|(a,b)| a != b).count() == 1 {
let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
println!("String without the different character: {}", newStr);
}
}
}
}
Error:
error[E0382]: use of moved value: `zipped`
--> a.rs:10:30
|
6 | let zipped = s2.chars().zip(s1.chars());
| ------ move occurs because `zipped` has type `Zip<Chars<'_>, Chars<'_>>`, which does not implement the `Copy` trait
...
9 | if zipped.filter(|(a,b)| a != b).count() == 1 {
| ---------------------- `zipped` moved due to this method call
10 | let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
| ^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `zipped`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
Upvotes: 2
Views: 256
Reputation: 7927
You can always zipped.clone()
, which clones the iterator so that you move the clone when you first call to filter(...).count()
. The original zipped
remains untouched and you'll move it by the second filter(...).collect()
.
Note that it doesn't clone any data because iterators are lazy, copying an iterator means to copy its logic (so it copies logic of .chars()
, .zip()
etc which is just a bunch of function pointers, not the data).
fn main() {
let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];
for s1 in &data {
for s2 in &data {
let zipped = s2.chars().zip(s1.chars());
// << THE CHANGE IS HERE
if zipped.clone().filter(|(a,b)| a != b).count() == 1 {
let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
println!("String without the different character: {}", newStr);
}
}
}
}
Output:
String without the different character: bc
String without the different character: bc
Upvotes: 2