如何在循环中使用可变状态?
How to use mutable state in a loop?
循环:
impl State {
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(&[u8], SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
报错:
error[E0499]: cannot borrow `state` as mutable more than once at a time
--> src/main.rs:93:14
|
93 | let new = state.exec();
| ^^^^^ `state` was mutably borrowed here in the previous iteration of the loop
然而,如果我注释掉 packets.extend(new);
行,则没有错误。
我认为问题是返回的vector属于state
,好像new
在循环迭代之前被丢弃了,没问题。我很高兴复制返回的矢量,如果这样可以解决问题的话。
我预计将 .clone()
添加到 new
或 state.exec()
会修复它,但它没有。
有解决这个问题的简单方法吗?
或者我是否需要以不同的方式构造单线程应用程序状态?
一个解决方案是:
impl State {
pub fn exec(&mut self) -> Vec<(Vec<u8>, SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(Vec<u8>, SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
我不确定这是不是最好的解决方案,所以我会暂时搁置这个问题。
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)>
让我们加入 implicit lifetimes
pub fn exec<'a>(&'a mut self) -> Vec<(&'a [u8], SocketAddr)>
因此返回的切片必须具有与可变借用 相同的 生命周期。现在,您将如何处理返回的切片?
let new = state.exec();
packets.extend(new);
我们将其存储在packets
中。所以 state
的借用必须至少持续到 packets
的类型,这就是整个函数。因此,从循环的第一次迭代到函数的最后,我们再也不能借用 state
,因为可变借用一直持续到函数结束。
要问自己的第一个问题是:您真的需要可变借用吗?如果你可以下降到 &self
,那么就这样做,你的问题就解决了。否则,您将需要以某种方式重组事物。类型 &[u8]
本质上是无主的。这是对 其他人的 数据的引用。如果您获取该数据的唯一方法是通过 &mut self
,那么您将永远无法按照您想要的方式循环。因此,要克隆数据,您需要使用 to_vec
,它将 &[u8]
变成 Vec<u8>
(您的类型签名必须更改以反映这一点)。
只需更改函数签名,使返回的 &[u8]
不借用 *self
即可编译示例代码:
pub fn exec<'a>(&mut self) -> Vec<(&'a [u8], SocketAddr)> {
vec![]
}
请注意 'a
是一个自由生命周期参数,因此调用者可以在那里提供任何内容(包括 'static
)和任何引用 exec
returns 必须满足调用者提供的生命周期。实际上,这意味着 Vec
只能包含 'static
引用,因为 'static
是唯一的生命周期,它是所有其他生命周期的子类型。
这不太可能是您想要的。但是,它可能是,或者 [u8]
可能是从其他参数(而不是 *self
)借来的,或者是从 *self
中包含的引用重新借来的。这表明,只需更改签名以更准确地表示输入和输出之间的生命周期关系,有时就可以在不进行任何其他更改的情况下修复此类错误。
循环:
impl State {
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(&[u8], SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
报错:
error[E0499]: cannot borrow `state` as mutable more than once at a time
--> src/main.rs:93:14
|
93 | let new = state.exec();
| ^^^^^ `state` was mutably borrowed here in the previous iteration of the loop
然而,如果我注释掉 packets.extend(new);
行,则没有错误。
我认为问题是返回的vector属于state
,好像new
在循环迭代之前被丢弃了,没问题。我很高兴复制返回的矢量,如果这样可以解决问题的话。
我预计将 .clone()
添加到 new
或 state.exec()
会修复它,但它没有。
有解决这个问题的简单方法吗?
或者我是否需要以不同的方式构造单线程应用程序状态?
一个解决方案是:
impl State {
pub fn exec(&mut self) -> Vec<(Vec<u8>, SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(Vec<u8>, SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
我不确定这是不是最好的解决方案,所以我会暂时搁置这个问题。
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)>
让我们加入 implicit lifetimes
pub fn exec<'a>(&'a mut self) -> Vec<(&'a [u8], SocketAddr)>
因此返回的切片必须具有与可变借用 相同的 生命周期。现在,您将如何处理返回的切片?
let new = state.exec();
packets.extend(new);
我们将其存储在packets
中。所以 state
的借用必须至少持续到 packets
的类型,这就是整个函数。因此,从循环的第一次迭代到函数的最后,我们再也不能借用 state
,因为可变借用一直持续到函数结束。
要问自己的第一个问题是:您真的需要可变借用吗?如果你可以下降到 &self
,那么就这样做,你的问题就解决了。否则,您将需要以某种方式重组事物。类型 &[u8]
本质上是无主的。这是对 其他人的 数据的引用。如果您获取该数据的唯一方法是通过 &mut self
,那么您将永远无法按照您想要的方式循环。因此,要克隆数据,您需要使用 to_vec
,它将 &[u8]
变成 Vec<u8>
(您的类型签名必须更改以反映这一点)。
只需更改函数签名,使返回的 &[u8]
不借用 *self
即可编译示例代码:
pub fn exec<'a>(&mut self) -> Vec<(&'a [u8], SocketAddr)> {
vec![]
}
请注意 'a
是一个自由生命周期参数,因此调用者可以在那里提供任何内容(包括 'static
)和任何引用 exec
returns 必须满足调用者提供的生命周期。实际上,这意味着 Vec
只能包含 'static
引用,因为 'static
是唯一的生命周期,它是所有其他生命周期的子类型。
这不太可能是您想要的。但是,它可能是,或者 [u8]
可能是从其他参数(而不是 *self
)借来的,或者是从 *self
中包含的引用重新借来的。这表明,只需更改签名以更准确地表示输入和输出之间的生命周期关系,有时就可以在不进行任何其他更改的情况下修复此类错误。