2016-11-26 4 views
1

Я пытаюсь генерировать Vec<(Point, f64)>:Повторное использование связывания в Rust закрытия

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 в обоих элементов кортежа, но когда я пытаюсь сохранить ссылку, я получаю сообщение об ошибке на всю жизнь.

+0

Можете ли вы представить пример полной компиляции (даже с ошибкой), предпочтительно, который будет работать на play.rust-lang.org? Было бы легче убедиться, какую ошибку вы получаете и где, и предложить исправить. –

ответ

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 link

нотабене если вы хотите сохранить заказ:

.map(|(a, b)| (b, a)) 
+1

С другой стороны, 'Point' не реализует [' Copy'] (https://doc.rust-lang.org/std/marker/trait.Copy.html). Вы также можете использовать временную переменную - .map (| point | {let d = point.distance_to (& origin); (point, d)}) '. – Shepmaster

 Смежные вопросы

  • Нет связанных вопросов^_^