2016-11-26 1 views
1

Je cherche à générer un Vec<(Point, f64)>:réutilisation obligatoire dans la fermeture 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)>>(); 

Je reçois l'erreur suivante:

use of moved value: point 

Je comprends que je ne peux pas utiliser point dans les deux éléments du tuple, mais quand je tente de stocker une référence, j'obtiens une erreur concernant la durée de vie.

+0

Pouvez-vous fournir un exemple complet compilable (même avec une erreur), de préférence qui fonctionnera sur play.rust-lang.org? Il serait plus facile d'être sûr de l'erreur que vous obtenez et où, et de proposer une solution. –

Répondre

1

Je suppose votre Point struct se présente comme suit:

#[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() 
    } 
} 

Maintenant, regardons un exemple encore plus simple qui ne compilera pas:

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

Ce qui donne l'erreur:

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 

Parce que x a été déplacé dans y, il ne peut maintenant pas avoir de référence prise pour appeler la fonction distance_to.

La chose importante à noter ici est que les questions d'ordre - si nous échangeons les lignes sur nous pouvons appeler distance_to en empruntant x, l'emprunt prendra fin et alorsx peut être déplacé dans y.

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

Dans votre cas, une chose très similaire se produit lors de la construction du tuple. point est déplacé dans le tuple, et puis essaie de l'emprunter pour former le deuxième élément. La solution la plus simple est de faire la même chose qu'ici: permuter l'ordre des éléments du tuple.

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

Playground link

N.B. si vous souhaitez conserver l'ordre:

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

D'une autre manière, 'Point' n'implémente pas [' Copy'] (https://doc.rust-lang.org/std/marker/trait.Copy.html). Vous pouvez également utiliser une variable temporaire - '.map (| point | {let d = point.distance_to (& origine); (point, d)})'. – Shepmaster