提问人:Fajela Tajkiya 提问时间:8/10/2022 更新时间:8/10/2022 访问量:189
我应该什么时候进行闭包静音?
When should I make a closure mut?
问:
假设我有这段代码:
let mut s = "hi".to_string();
let c = || s.push_str(" yo");
c();
它不会编译并生成此错误:
error[E0596]: cannot borrow `c` as mutable, as it is not declared as mutable
--> src\test.rs:120:9
|
119 | let c = || s.push_str(" yo");
| - - calling `c` requires mutable binding due to mutable borrow of `s`
| |
| help: consider changing this to be mutable: `mut c`
120 | c();
| ^ cannot borrow as mutable
For more information about this error, try `rustc --explain E0596`.
error: could not compile `test` due to previous error
为什么借款不能变?它不能借用什么作为可变的??为了让它工作,我必须将其更改为:c();
c
let mut s = "hi".to_string();
let mut c = || s.push_str(" yo");
c();
但在这里我只是定义一个闭包.我不会修改它,比如.为什么必须将其定义为?c
c = || x;
let mut c
答:
它可能看起来不需要可变,因为你没有修改自己,但对于闭包类型,关键字是允许它改变任何外部状态的东西。它将闭包的类型更改为 FnMut
,文档将其称为“可变捕获闭包”。c
c
mut
这是关于所有权的。 这里并不意味着你会变异,而是你需要对闭包的-level访问权限才能执行它。mut
c
mut
c
可变借用。这应该是相当明显的,因为调用会修改 .s
c()
s
现在想象一下,如果没有:c
mut
let mut s = "hi".to_string();
let c = || s.push_str(" yo");
let c1 = &c;
let c2 = &c;
c1();
c2();
在这里,两者同时具有可变访问权限,根据 Rusts 借用规则,这是不可能的。编译器会自动阻止这种情况,因为它会在您从闭包内可变访问变量时立即更改闭包的类型。c1
c2
s
FnMut
然后,您需要访问闭包才能执行它,并且情况会变成编译器错误:mut
let mut s = "hi".to_string();
let mut c = || s.push_str(" yo");
let c1 = &mut c;
let c2 = &mut c;
c1();
c2();
error[E0499]: cannot borrow `c` as mutable more than once at a time
--> src/main.rs:5:10
|
4 | let c1 = &mut c;
| ------ first mutable borrow occurs here
5 | let c2 = &mut c;
| ^^^^^^ second mutable borrow occurs here
6 |
7 | c1();
| -- first borrow later used here
但在这里我只是定义一个闭包.我不会修改它,比如.为什么必须将其定义为 let ?
c
c = || x;
mut c
因为闭包从根本上说是一个结构,每个捕获的项都是该结构的成员。
所以你的代码大致相当于这个:
struct S<'a>(&'a mut String);
impl S<'_> {
fn call(&mut self) {
self.0.push_str("yo");
}
}
fn main() {
let mut s = "hi".to_string();
let c = S(&mut s);
c.call();
}
并且无法编译或多或少相同的错误:
error[E0596]: cannot borrow `c` as mutable, as it is not declared as mutable
--> src/main.rs:14:5
|
13 | let c = S(&mut s);
| - help: consider changing this to be mutable: `mut c`
14 | c.call();
| ^^^^^^^^ cannot borrow as mutable
现在你可能会反对,那是因为我定义了,但如果你不这样做,你会得到相同错误的内部部分:fn call(&mut self)
error[E0596]: cannot borrow `*self.0` as mutable, as it is behind a `&` reference
--> src/main.rs:8:9
|
7 | fn call(&self) {
| ----- help: consider changing this to be a mutable reference: `&mut self`
8 | self.0.push_str("yo");
| ^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
也就是说,您不能通过 .因为如果你这样做了,你可以创建多个 s,通过它你可以修改 pointee,这基本上会给你多个 .&mut
&
&
&mut
&mut
这是 Rust 的语义所不允许的:
在任何给定时间,都可以有一个可变引用,也可以有任意数量的不可变引用。
评论