【问题标题】:What is the syntax to match on a reference to an enum?对枚举的引用匹配的语法是什么?
【发布时间】:2016-04-13 06:44:09
【问题描述】:

似乎 Rust 的 enum types 的每个介绍性文档都解释了如何在您拥有的枚举对象上使用 match,但是如果您不拥有该枚举对象而您只有一个引用它,你想匹配?我不知道语法是什么。

这是我尝试匹配枚举引用的一些代码:

use std::fmt;
use std::io::prelude::*;

pub enum Animal {
    Cat(String),
    Dog,
}

impl fmt::Display for Animal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Animal::Cat(c) => f.write_str("c"),
            Animal::Dog => f.write_str("d"),
        }
    }
}

fn main() {
    let p: Animal = Animal::Cat("whiskers".to_owned());
    println!("{}", p);
}

Rust Playground 在尝试编译时在匹配的前两种情况下给出错误:

error[E0308]: mismatched types
  --> src/main.rs:12:13
   |
12 |             Animal::Cat(c) => f.write_str("c"),
   |             ^^^^^^^^^^^^^^ expected &Animal, found enum `Animal`
   |
   = note: expected type `&Animal`
   = note:    found type `Animal`

error[E0308]: mismatched types
  --> src/main.rs:13:13
   |
13 |             Animal::Dog => f.write_str("d"),
   |             ^^^^^^^^^^^ expected &Animal, found enum `Animal`
   |
   = note: expected type `&Animal`
   = note:    found type `Animal`

如何更改该代码以使其编译?我尝试在许多不同的地方添加&符号,但没有任何运气。甚至可以匹配对枚举的引用吗?

【问题讨论】:

标签: rust


【解决方案1】:

编辑:请参阅 Shepmaster 对最新成语的回答

惯用的方式是

match *self {
    Animal::Cat(ref c) => f.write_str("c"),
    Animal::Dog => f.write_str("d"),
}

您可以使用_ 而不是ref c 来消除“未使用”警告。

【讨论】:

  • .. 忽略多个值。
  • 这与下面的答案 (stackoverflow.com/a/36590693/86381) 有什么区别,其中匹配的每个分支都以 & 开头?
  • @ehdv 我不这么认为,但我还没有比较生成的程序集。
  • 我至少见过一次代码,其中另一个答案可以正常编译,但这个代码会抱怨“无法移出借来的内容”。
  • 如何在第一个匹配分支臂中引用内部类型c?
【解决方案2】:

从 Rust 1.26 开始,惯用方式是你最初编写它的方式because match ergonomics have been improved:

use std::fmt;

pub enum Animal {
    Cat(String),
    Dog,
}

impl fmt::Display for Animal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Animal::Cat(_) => f.write_str("c"),
            Animal::Dog => f.write_str("d"),
        }
    }
}

fn main() {
    let p: Animal = Animal::Cat("whiskers".to_owned());
    println!("{}", p);
}

【讨论】:

  • 我通过玩弄发现了一些额外的微妙之处: 1. 你可以在内部值c 前面保留ref,它的作用与没有相同(只要你删除& 在枚举变体前面)。 2. 如果在枚举变量Cat 前面保留&,但删除ref c,它将尝试移动/复制内部值c!对于借来的内容,它不能移出,并且无法编译。 3、&mut Enum::Variant(ref mut value)中的&mutref mut也可以跳过。你仍然必须写*value = new_value。抱歉,由于评论限制导致格式错误。
  • 在 Rust Book 中找到了一个示例(虽然不是 mut):doc.rust-lang.org/book/… 清单 15-25
  • 但是为什么呢?该规则有解释吗?
  • @chylli 更新了指向the RFC that make the changes 的链接。这就是你要找的东西吗?
  • @Jay Dog(v) => write!(f, “blah {}”, v),doc.rust-lang.org/book/ch06-02-match.html
【解决方案3】:

感谢有用的编译器消息,我想通了:

match self {
    &Animal::Cat(ref c) => f.write_str("c"),
    &Animal::Dog => f.write_str("d"),
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-26
    • 2016-06-25
    • 2023-04-07
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多