我在 match
表达式中使用 self
时遇到了问题:
fn add_once(&'t mut self, p_name: &'t str) -> Box<Element> {
match self.get(p_name) {
Some(x) => Box::new(*x),
None => self.add(p_name),
}
}
get()
和 add()
函数的签名如下:
fn get(&self, p_name: &str) -> Option<&Element>
fn add(&'t mut self, p_name: &'t str) -> Box<Element>
编译器拒绝了这段代码:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/main.rs:38:21
|
36 | match self.get(p_name) {
| ---- immutable borrow occurs here
37 | Some(x) => Box::new(*x),
38 | None => self.add(p_name),
| ^^^^ mutable borrow occurs here
39 | }
40 | }
| - immutable borrow ends here
我理解,但我不知道如何重写match
表达式。
在相关问题中,通过让match
返回一个值并调用函数来解决了这个问题。然而,在这里不起作用,因为条件语句的含义不是选择一个值而是有选择地执行一个操作。
下面是完整的代码示例:
struct Element<'e> {
name: &'e str,
}
impl<'e> Element<'e> {
fn new(p_name: &str) -> Element {
Element { name: p_name }
}
}
struct Top<'t> {
list: Vec<Element<'t>>,
}
impl<'t> Top<'t> {
fn new() -> Top<'t> {
Top { list: vec![] }
}
fn get(&self, p_name: &str) -> Option<&Element> {
for element in self.list.iter() {
if element.name == p_name {
return Some(element);
}
}
None
}
fn add(&'t mut self, p_name: &'t str) -> Box<Element> {
let new_element = Box::new(Element::new(p_name));
self.list.push(*new_element);
return new_element;
}
fn add_once(&'t mut self, p_name: &'t str) -> Box<Element> {
match self.get(p_name) {
Some(x) => Box::new(*x),
None => self.add(p_name),
}
}
}
fn main() {
let mut t = Top::new();
let plop1 = t.add_once("plop1");
let plop2 = t.add_once("plop1");
}
match
的两个分支应该返回相同的类型。同样,我很惊讶add
编译通过,因为您首先将内容推入向量,然后再返回;但是在我的看法中,将内容推入向量应该使盒子的内容无效(移动)...add
不应该返回&Element
,而add_once
的结果应该是&Element
吗? - Matthieu M.Element
是Copy
,所以*new_element
返回元素的副本。 - Vladimir MatveevCopy
还没有选择加入。不过,对我来说,这似乎表明了一个设计缺陷:Top
看起来应该是通用的,并且适用于非Copy
类型。 - Matthieu M.add
和add_once
返回&Element
,但无法使其正常工作。 - Tifauv'