Why do the vector values not get move to the Ordering function in the below code?
I am a Rust noob and I have been going through a few videos and articles. I was following this article here about Rust iterators.
When it is explaining iter_mut()
it uses the following example.
fn main() {
let mut teams = [
[ ("Jack", 20), ("Jane", 23), ("Jill", 18), ("John", 19), ],
[ ("Bill", 17), ("Brenda", 16), ("Brad", 18), ("Barbara", 17), ]
];
let teams_in_score_order = teams
.iter_mut()
.map(|team| {
team.sort_by(|&a, &b| a.1.cmp(&b.1).reverse());
team
})
.collect::<Vec<_>>();
println!("Teams: {:?}", teams_in_score_order);
}
Here team.sort_by(|&a, &b| a.1.cmp(&b.1).reverse())
VS Code tells me that these are the variable types.
a: (&str, i32)
b: (&str, i32)
So here in the closure a.1.cmp(&b.1).reverse()
, a
is not a borrowed value (according to my current understanding). So why wouldn't it get dropped at the end of the closure? I am assuming, that if a
gets dropped, then there would not be any items left in the vector at the end of this function. One more question: Once a value is passed as a borrowed value, what does it mean to access without the &
?
Also, I was trying to understand, defining closure parameters using &
. I understand &
means to reference/borrow a value. However here, I removed &
from |&a, &b|
and it still worked, but at that point, types were defined as
a: &(&str, i32)
b: &(&str, i32)
. Here what does it mean by having or not having &
in the parameter definition in |&a, &b|
?
Thanks in advance!
It does not get moved because (&str, i32)
implements Copy (as both &str
and i32
both implement Copy), so instead of moving it just copies the tuple.
You can test this by trying to compile this:
fn main() {
let mut teams = [
[ ("Jack".to_owned(), 20), ("Jane".to_owned(), 23), ("Jill".to_owned(), 18), ("John".to_owned(), 19), ],
[ ("Bill".to_owned(), 17), ("Brenda".to_owned(), 16), ("Brad".to_owned(), 18), ("Barbara".to_owned(), 17), ]
];
let teams_in_score_order = teams
.iter_mut()
.map(|team| {
team.sort_by(|&a, &b| a.1.cmp(&b.1).reverse());
team
})
.collect::<Vec<_>>();
println!("Teams: {:?}", teams_in_score_order);
}
Rust Playground
The compiler will now complain that it is being moved, since the type is now (String, i32)
, and String
does not implement Copy.
Also, I was trying to understand, defining closure parameters using &.
I believe using & when defining arguments in a closure is just sugar for the de-referencing each variable. E.g.
|&a, &b| a.1.cmp(&b.1).reverse()
is the same as
|a, b| {
let a = *a;
let b = *b;
a.1.cmp(&b.1).reverse()
}
Though I am not 100% sure this is correct.