【问题标题】:Reuse binding in Rust closure在 Rust 闭包中重用绑定
【发布时间】:2025-12-03 23:40:01
【问题描述】:

我正在尝试生成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,但是当我尝试存储引用时,我收到关于生命周期的错误。

【问题讨论】:

  • 您能否提供一个完整的可编译(即使有错误)示例,最好在 play.rust-lang.org 上运行?更容易确定您遇到了什么错误,在哪里,并提出修复建议。

标签: rust closures borrow-checker borrowing


【解决方案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 函数。

这里要注意的重要一点是顺序很重要 - 如果我们交换线路,我们可以通过借用 x 来调用 distance_to,借用将结束,然后 x 可以搬到y

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

在您的情况下,构造元组时发生了非常相似的事情。 point 被移动到元组中,then 尝试借用它来形成第二个元素。最简单的解决方案是做和这里一样的事情:交换元组元素的顺序。

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))

【讨论】:

  • 换一种说法,Point 没有实现Copy。您还可以使用临时变量 - .map(|point| { let d = point.distance_to(&amp;origin); (point, d) })