我正在尝试编写一个函数,该函数查找返回对 Vec 中现有元素的可变引用,或者如果不存在则将其插入并返回对新元素的可变引用。
我已经尝试过几次,但借用检查员不相信。我已将尝试编写的代码简化为下面的示例,该示例给出了相同的错误。
fn mut_find_or_insert<T: PartialEq>(vec: &mut Vec<T>, val: T) -> &mut T {
if let Some(u) = vec.iter_mut().find(|u| **u == val) {
u
} else {
vec.push(val);
vec.last_mut().unwrap()
}
}
游乐场链接:
Rust 给了我以下编译器错误(完整消息通过游乐场链接):
error[E0499]: cannot borrow `*vec` as mutable more than once at a time
这似乎应该可以在 Rust 中实现,但是我不清楚如何重新实现它以避免借用检查器错误。
这不能按书面方式工作的原因是当前借用检查器的限制。这非常类似于NLL 案例 #3,其中编译器过度热心地借用了整个match
当借用仅在其中一个分支中使用时的语句。使用实验性的“Polonius”借用检查器(可在夜间编译器上使用-Z polonius
标志),您的代码将按原样接受。
在稳定的编译器中工作,重新设计数据结构可能是个好主意塞巴斯蒂安·雷诺的回答也建议,但如果你需要让这个工作与Vec
,您可以通过简单地使用索引来结束借用来解决这个问题:
fn mut_find_or_insert<T: PartialEq>(vec: &mut Vec<T>, val: T) -> &mut T {
if let Some(i) = vec.iter().position(|each| *each == val) {
&mut vec[i]
} else {
vec.push(val);
vec.last_mut().unwrap()
}
}
这是有效的,因为调用的结果position
不是参考,所以借用vec
期间不举行if let
.
这类似于以下问题,这些问题设法使用循环的早期返回来找到相同的限制:
- 即使 NLL 打开,循环中的双重可变借用错误也会发生
- 当返回包含引用的结果时,“变量的寿命不够长”,但它确实寿命足够长
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)