rust 在FnMut闭包内重新绑定拥有的变量

jljoyd4f  于 2023-02-16  发布在  其他
关注(0)|答案(1)|浏览(115)

我无法重新绑定一个已经被移到FnMut()闭包中的自有变量。我想下面的MRE总结了这个问题。

fn takes_closure(mut do_something: impl FnMut()) {
    do_something()
}

fn main() {
    let test_string = String::from("hello");

    takes_closure(move || {
        //let mut test_string = test_string; // 1
        let mut test_string = test_string.clone(); // 2
        test_string.push_str("!"); // 3
    });
}

目标行为将是每次调用闭包时test_string都有一个!附加到其上。请注意,由于原始问题的上下文,不可能将test_string重新绑定到main中作为可变的。我发现了以下问题:
1.是不可能的,因为这是“移动”出封闭
1.是不正确的,因为我现在修改的是字符串的副本,而不是原始字符串
1.仅适用于#2,因为它要求test_string可变绑定。

ryevplcw

ryevplcw1#

您可以在闭包之前将test_string声明为可变的,或者直接将原始变量设置为可变的:

fn main() {
    let mut test_string = String::from("hello");

    takes_closure(move || {
        test_string.push_str("!"); // 3
    });
}

或者,如果您希望在闭包之前保持不变性,则在闭包外部重新绑定变量

fn main() {
    let test_string = String::from("hello");

    takes_closure({
        let mut test_string = test_string;
        move || {
            test_string.push_str("!"); // 3
        }
    });
}

如果你想修改原始的test_string并观察闭包运行后的变化,你只需要移动一个可变的引用:

fn main() {
    let mut test_string = String::from("hello");

    takes_closure({
        let test_string = &mut test_string;
        move || {
            test_string.push_str("!"); // 3
        }
    });

    dbg!(test_string); // outputs 'test_string = "hello!"'
}

相关问题