【问题标题】:Apparent unused variable in match statement匹配语句中明显未使用的变量
【发布时间】:2022-06-19 06:13:02
【问题描述】:

我正在实施一个简单的图书馆系统来跟踪我的 pdf。

我有一个Subject 枚举和一个Entry 结构,定义如下:

pub enum Subject {

    Math,
    Programming,
    CompSci,
    Language,
    Misc,
    None
}

pub struct Entry {

    pub subject: Subject

}

我正在尝试实现一个函数,该函数将对Entry 的向量进行操作并返回一个Vec<&Entry>,其条目与给定的Subject 匹配。

我有一个简单的 Library 结构,它是 Vec<Entry> 的包装器:

pub struct Library {

    pub entries: Vec<Entry>

}

为此,我只需要遍历entriesfilter 的元素,其.subject 字段对应于所需的subject。为此,我创建了一个返回谓词函数的函数。

这里是get_subject 函数:

impl Library {
    
    pub fn get_subject(&self, subject: Subject) -> Vec<&Entry> {

        let pred = subject_pred(subject);
        self.entries.iter().filter(pred).collect::<Vec<&Entry>>()
    }
}

调用函数subject_pred来创建正确的谓词函数:

// Return a PREDICATE that returns true when
// the passed ENTRY matches the desired SUBJECT
fn subject_pred(subject_UNUSED: Subject) -> impl FnMut(&&Entry) -> bool {
    |e: &&Entry| if matches!(&e.subject, subject_UNUSED) {
        true
    } else {
        false
    }
}

这是问题。这种语法编译得很好,但显然subject_pred 中的subject_UNUSED 局部变量是“未使用的”。我大吃一惊,因为我的语法清楚地表明了与传递的subject_UNUSED 匹配的意图。当我在一个条目向量上测试这个函数时,谓词 always 返回 true(因此我收到“未使用”警告),但我真的不知道为什么。

如果有人能解释为什么match 语句总是匹配,那将不胜感激。我尝试使用常规的match 语句,但弹出了相同的警告,这不是我要编码的行为。如果我在传统的match 语句中不包含subject_UNUSED,编译器会告诉我必须覆盖MathProgrammingCompSciLanguageMisc 和@987654351 @ 我的枚举的变体,这向我表明在那之前的一切都很好。

【问题讨论】:

  • 这个签名 - pub fn get_subject(entries: Vec&lt;Entry&gt;, subject: Subject) -&gt; Vec&lt;&amp;Entry&gt; - 是行不通的:你不能拿一个拥有的 Entry 并产生一个借来的。
  • 我实际上有一个Library 结构,它只是一个Vec&lt;Entry&gt; 的包装器,但我不想包含它以使事情复杂化。我会将它们包含在透明度编辑中

标签: rust enums match


【解决方案1】:

您无法匹配变量。你所做的相当于

matches!(&e.subject, some_subject)

匹配 any Subject,就像通配符 (_),除了它还在 some_subject 变量中捕获它(可以在像 matches!(&amp;e.subject, subject_UNUSED if subject_UNUSED == ...) 这样的守卫中使用) .既不使用捕获的变量,也不使用参数(被它遮蔽)。

你需要做的是#[derive(PartialEq)]然后使用==

if e.subject == subject_UNUSED { ... }

顺便说一句,您的代码还有其他问题:您没有 move 进入闭包并且您正在获取拥有的条目但产生借用。

【讨论】:

  • 感谢您的回复。我从一个简单的== 开始,但后来转到match,因为这是我在“比较”枚举时看到的。我将使用#[derive(PartialEq)] 作为解决方案。我之前在关闭时也有一个move 声明,但由于“没有改变任何东西”(从我无知的角度来看)我删除了它。我只是在语言中磕磕绊绊,发现它比我过去学到的任何东西都要困难得多。书中没有提到“你不能匹配变量”。
  • @ejovo13 好吧,我学习 Rust 已经很久了,但是看这本书,它确实提到你匹配模式,我不认为它说变量就是模式。跨度>
  • 我明白你的意思,但我的反驳是,存储在我的变量中的值将是一个枚举变量,因此假设我可以匹配有效的模式并不是不合理的。这就像说我不能指望let x = 10; println!("{}", x); 打印出值10,因为我实际上并没有传递值10,而是传递了一个变量......关键是我不讨厌关于这本书的作者 - 太棒了 - 这只是其中一件事,当你尝试一些不起作用的东西时,你才知道语言的局限性。
  • @ejovo13 那么您在变量中存储的不是模式(you can't do that)而是一个值,以及您在变量中分配的10(或枚举变量)声明不是模式而是表达式。然而,为此争论是相当多余的。现在你明白了,这很重要。
  • 无意争辩!这是一个学习过程,是的,现在我明白了,这很重要:)。只是屈服于我保护自己的原始愿望;)。再次感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 2010-12-06
相关资源
最近更新 更多