rust - 为什么我不能可变地移动捕获不可变变量?

标签 rust closures immutability

我有一个创建 FnMut 闭包的函数,move - 捕获其中一个参数。我收到编译器错误,因为参数不是 mut。我不明白问题是什么,因为我移动它并且闭包并没有真正使用参数本身。

代码:

pub struct Position {
    pub x: usize,
    pub y: usize,
}

fn map_it(p: Position) -> impl FnMut(usize) -> usize {
    move |param| {
        p.x += 1;
        p.x + p.y + param
    }
}

错误:

error[E0594]: cannot assign to `p.x`, as `p` is not declared as mutable
 --> src/lib.rs:8:9
  |
6 | fn map_it(p: Position) -> impl FnMut(usize) -> usize {
  |           - help: consider changing this to be mutable: `mut p`
7 |     move |param| {
8 |         p.x += 1;
  |         ^^^^^^^^ cannot assign

最佳答案

即使移动了变量 p,您也没有引入新的变量绑定(bind)。绑定(bind) p 是不可变的,因此您不能通过 p 改变值。

闭包实际上是一个看起来(有点)像这样的结构:

struct MyClosure {
    p: Position,
}

impl FnMut<usize, usize> for MyClosure {
    fn call_mut(&mut self, param: usize) -> usize {
        self.p.x += 1;
        self.p.x + p.y + param
    }
}

由此看来,p应该在闭包内部是可变的,这绝对是令人信服的。

但是,Rust 避免直接公开此实现细节。变量 p 的可变性语义是词法的,就像闭包主体是外部函数的一部分一样。

您无法在闭包中使此变量可变。相反,您需要使原始 p 可变或在闭包外部引入新的可变绑定(bind)。

关于rust - 为什么我不能可变地移动捕获不可变变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57381861/

相关文章:

javascript - 函数作为 JavaScript 的返回类型

swift - 创建 Swift 闭包以创建 UIView

javascript - 如何将 "inject"变量转入匿名函数

multithreading - 使用rusoto使用rust AWS分段上传,对 'there is no reactor running …`感到 panic 的多线程(人造丝)

rust - Rust 教科书的猜谜游戏扩展显示出奇怪的行为

rust - 我怎样才能对 Option<String> 进行模式匹配?

c++ - 不可变树的高效随机更新

.NET:GC 何时运行?内存泄漏?

javascript - 如何使 JavaScript 变量完全不可变?

rust - 轻松将第三方错误转换为字符串