Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 可变自内匹配表达式_Rust - Fatal编程技术网

Rust 可变自内匹配表达式

Rust 可变自内匹配表达式,rust,Rust,我在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), } } 编译器拒绝此代码: error[E0502]:无法将“*self”作为可变

我在
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),
    }
}
编译器拒绝此代码:

error[E0502]:无法将“*self”作为可变项借用,因为它也是作为不可变项借用的
-->src/main.rs:38:21
|
36 |匹配自我获取(p|U名称){
|----此处发生不可变借用
37 |一些(x)=>Box::new(*x),
38 | None=>self.add(p|u name),
|^^^^^此处发生可变借用
39 |         }
40 |     }
|-不可变的借阅到此结束
我明白了,但我不知道如何重写
match
表达式

在a中,通过让
匹配
返回一个值,然后调用函数来解决这个问题。但是,这在这里不起作用,因为条件的含义不是选择一个值,而是有选择地执行一个操作

完整的代码示例如下:

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");
}
struct元素{
fn新(p_名称:&str)->元素{
元素{name:p_name}
}
}
结构顶部>,
}
恳求{

fn new()->Top让我们先解决设计问题。主要问题是生命周期合并:

struct Top<'t> {
    list: Vec<Element<'t>>,
}

impl<'t> Top<'t> {
    fn add(&'t mut self, p_name: &'t str) -> Box<Element>;
    fn add_once(&'t mut self, p_name: &'t str) -> Box<Element>;
}
请注意,
元素
的引用的生存期
'a
不同于其包含的引用的生存期
't

这样,就可以修复以下功能:

fn position(&self, p_name: &str) -> Option<usize> {
    self.list.iter().position(|e| e.name == p_name)
}

fn add<'a>(&'a mut self, p_name: &'t str) -> &'a Element<'t> {
    self.list.push(Element::new(p_name));
    &self.list[self.list.len() - 1]
}

fn add_once<'a>(&'a mut self, p_name: &'t str) -> &'a Element<'t> {
    if let Some(p) = self.position(p_name) {
        return &self.list[p];
    }
    self.add(p_name)
}

我希望在一个完美的世界里,以下几点能够奏效:

fn add_once<'a>(&'a mut self, p_name: &'t str) -> &'a Element<'t> {
    match self.get(p_name) {
        Some(x) => x,
        None => self.add(p_name)
    }
}

fn add\u onceen即使没有可变错误,您仍然会有一个类型统一问题。
match
的两个分支都应该返回相同的类型。同样,我感到惊讶的是,
add
在您第一次
推入向量然后返回时编译;然而,在我看来,推入向量应该无效te(移动)框的内容…不应该
add
返回
&Element
,而
add\u once
的结果应该是
&Element
?@MatthieuM.,它起作用是因为
Element
Copy
,所以
*new\u Element
返回元素的副本。@Vladimitveev:啊,是的,我忘了
Copy
不是然而,选择加入。不过,在我看来,这似乎表明了一个设计缺陷:
Top
似乎应该是泛型的,并且可以处理非
Copy
类型。我对锈迹非常陌生,所以可能存在设计错误。Top确实应该处理非
Copy
类型。@MatthieuM。最初,我想要
add
add\u once
来恢复n
&Element
,但无法使其工作。您在“完美世界”中完全正确备注。这不起作用,因为借词是词法的,但它们将来可能会变成非词法的,这将允许这种模式。据我所知,这是在
libstd
的映射中引入
Entry
API的主要原因之一(另一个原因当然是希望减少查找量)@VladimirMatveev:我希望它能得到扩展,在
if
中使用无可辩驳的模式是一个很好的解决办法,但这意味着失去
匹配
@MatthieuM的详尽性检查。谢谢,我对生存期有了更多的了解。事实上,
添加
添加一次
返回的引用的生存期与元素本身。需要一点大脑训练,但看起来不错。然而,编译器抱怨
fn@Tifauv“:很抱歉,
fn在
push
index
之间不可能存在竞争条件吗?如果
Vec.push
返回插入的元素,则会更简单。
fn position(&self, p_name: &str) -> Option<usize> {
    self.list.iter().position(|e| e.name == p_name)
}

fn add<'a>(&'a mut self, p_name: &'t str) -> &'a Element<'t> {
    self.list.push(Element::new(p_name));
    &self.list[self.list.len() - 1]
}

fn add_once<'a>(&'a mut self, p_name: &'t str) -> &'a Element<'t> {
    if let Some(p) = self.position(p_name) {
        return &self.list[p];
    }
    self.add(p_name)
}
fn get<'a>(&'a self, p_name: &str) -> Option<&'a Element<'t>> {
    self.position(p_name).map(|pos| &self.list[pos])
}
fn add_once<'a>(&'a mut self, p_name: &'t str) -> &'a Element<'t> {
    match self.get(p_name) {
        Some(x) => x,
        None => self.add(p_name)
    }
}