Повторно използване на обвързването в Rust затваряне

Опитвам се да генерирам Vec<(Point, f64)>:

let grid_size = 5;

let points_in_grid = (0..grid_size).flat_map(|x| {
    (0..grid_size)
        .map(|y| Point::new(f64::from(x), f64::from(y)))
        .collect::<Vec<Point>>()
});

let origin = Point::origin();

let points_and_distances = points_in_grid
    .map(|point| (point, point.distance_to(&origin)))
    .collect::<Vec<(Point, f64)>>();

Получавам следната грешка:

use of moved value: point

Разбирам, че не мога да използвам point и в двата елемента на кортежа, но когато се опитам да съхраня препратка, получавам грешка относно живота.


person davenportw15    schedule 26.11.2016    source източник
comment
Можете ли да предоставите пълен компилируем (дори с грешка) пример, за предпочитане който ще работи на play.rust-lang.org? Би било по-лесно да сте сигурни каква грешка получавате и къде и да предложите поправка.   -  person Chris Emerson    schedule 26.11.2016


Отговори (1)


Предполагам, че вашата Point структура изглежда по следния начин:

#[derive(Debug)]
struct Point(f64, f64);

impl Point {
    fn new(x: f64, y: f64) -> Self { Point(x, y) }
    fn origin() -> Self { Point(0.,0.) }
    fn distance_to(&self, other: &Point) -> f64 {
        ((other.0 - self.0).powi(2) + (other.1 - self.1).powi(2)).sqrt()
    }
}

Сега нека да разгледаме още по-прост пример, който няма да се компилира:

let x = Point::new(2.5, 1.0);
let y = x;
let d = x.distance_to(&y);

Което дава грешката:

error[E0382]: use of moved value: `x`
  --> <anon>:15:13
   |
14 |     let y = x;
   |         - value moved here
15 |     let d = x.distance_to(&y);
   |             ^ value used here after move
   |
   = note: move occurs because `x` has type `Point`, which does not implement the `Copy` trait

Тъй като x е преместено в y, сега не може да има препратка, за да извика функцията distance_to.

Важното, което трябва да се отбележи тук е, че редът има значение - ако разменим редовете, можем да извикаме distance_to чрез заемане на x, заемането ще приключи и след това x може да бъде преместено в y.

let x = Point(0., 0.);
let d = x.distance_to(&y);
let y = x; // compiles

Във вашия случай много подобно нещо се случва при конструирането на кортежа. point се премества в кортежа и след това се опитва да го заеме, за да формира втория елемент. Най-простото решение е да направите същото като тук: да размените реда на елементите на кортежа.

let points_and_distances = points_in_grid
    .map(|point| (point.distance_to(&origin), point))
    .collect::<Vec<(f64, Point)>>(); // compiles

Връзка към Playground

N.B. ако искате да запазите поръчката:

.map(|(a, b)| (b, a))
person Djzin    schedule 26.11.2016
comment
Казано по друг начин, Point не прилага Copy. Можете също така да използвате временна променлива - .map(|point| { let d = point.distance_to(&origin); (point, d) }). - person Shepmaster; 26.11.2016