Hello! I am reading topics about Closures of the book "Programming Rust" 2nd Edition. In the section of "Closures That Borrow" presenting a code snippet:
/// Sort by any of several different statistics.
fn sort_by_statistic(cities: &mut Vec<City>, stat: Statistic) {
cities.sort_by_key(|city| -city.get_statistic(stat));
}
Everything sounds right, but when I write a simple example to exam the code:
fn main() {
let mut cities = vec![
City {
name: String::from("New York"),
population: 99999,
area: 89098,
},
City {
name: String::from("Tokyo"),
population: 9999999,
area: 8989008,
},
];
sort_by_statistic(&mut cities, Statistic::Population);
println!("{:?}", cities);
}
#[derive(Debug)]
struct City {
name: String,
population: i64,
area: i64,
}
impl City {
fn get_statistic(&self, stat: Statistic) -> i64
{
match stat {
Statistic::Area => self.area,
Statistic::Population => self.population
}
}
}
enum Statistic {
Area,
Population,
}
fn sort_by_statistic(cities: &mut Vec<City>, stat: Statistic) {
cities.sort_by_key(|city| -city.get_statistic(stat));
}
I got this error:
cargo run
Compiling closures v0.1.0 (/home/nd/RustroverProjects/closures)
error[E0507]: cannot move out of stat
, a captured variable in an FnMut
closure
--> src/main.rs:42:51
|
41 | fn sort_by_statistic(cities: &mut Vec, stat: Statistic) {
| ---- captured outer variable
42 | cities.sort_by_key(|city| -city.get_statistic(stat));
| ------ ^^^^ move occurs because stat
has type Statistic
, which does not implement the Copy
trait
| |
| captured by this FnMut
closure
For more information about this error, try rustc --explain E0507
.
error: could not compile closures
(bin "closures") due to 1 previous error
So one way to make the code compile is to change the implementation of sort_by_statistic and get_statistic
which is
fn sort_by_statistic(cities: &mut Vec<City>, stat: Statistic) {
cities.sort_by_key(|city| -city.get_statistic(&stat));
}
fn get_statistic(&self, stat: &Statistic) -> i64
{
match stat {
Statistic::Area => self.area,
Statistic::Population => self.population
}
}
So I am wondering is it a typo of the book, or I am missing something? I mean is there any type whose reference that can be presented without "&"?
Which lead to the frustration the book states about:
In this case, when Rust creates the closure, it automatically borrows a reference to stat. It stands to reason: the closure refers to stat, so it must have a reference to it.
because looking at the code snippet and its explanation, it feels like the closure take the ownership of the value of stat variable and under the hood Rust is smart enough that it will only takes reference.