【问题标题】:Why can't I mutably move-capture an immutable variable?为什么我不能可变地移动捕获不可变的变量?
【发布时间】:2019-12-14 08:24:59
【问题描述】:

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

代码:

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

【问题讨论】:

  • 为什么你认为你应该能够改变一个没有标记为mut的变量?

标签: rust closures immutability


【解决方案1】:

即使变量p 已被移动,您也没有引入新的变量绑定。绑定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 可变或在闭包之外引入新的可变绑定。

【讨论】:

    猜你喜欢
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    • 2013-05-07
    • 2017-05-02
    相关资源
    最近更新 更多