【问题标题】:Is it possible to pattern match in Rust with multiple types?是否可以在 Rust 中使用多种类型进行模式匹配?
【发布时间】:2017-03-25 03:03:53
【问题描述】:

好像你做不到。如果没有,是否有计划支持添加它或运行时类型信息 (RTTI)?

struct Bus;
struct Car;
struct Person;

fn main() {
    let x = Bus;
    //or more realistically, let x = function_with_multiple_return_types();

    match x {
        Car => {
            // ...
        }
        Bus => {
            // this gets executed
        }
        Person => {
            // ...
        }
    }
}

这个例子很简单。在现实生活中,只有x 可以是多种类型才有用。例如let x = function_with_multiple_return_types();

【问题讨论】:

  • Idk Rust,但我希望匹配的每个子句都需要是相同的类型。尝试使它们都成为同一个超类/接口的一部分
  • 你能得到的最接近的可能是一个带标签的联合,例如示例here

标签: pattern-matching rust


【解决方案1】:

没有人可以 100% 准确地说某项功能会永远实现或不会实现,但我可以 100% 相信这永远不会实现。

这是为什么呢?因为建议的语法的好处为零。 Rust 是一种静态类型语言。这意味着编译器知道变量的类型是什么。除了Bus 之外的任何分支都不会被执行。一个变量不可能有多个类型!为什么要更改语言以允许您添加永远无法使用的代码?那不会很有用。

匹配语句和一般的模式匹配,只有在某事物有多种可能的变体时才真正有用。这就是 Rust 有 enums 的原因;允许一组固定的动态选择(也就是在运行时做出)。

如果您需要一组开放的动态决策,那就是特征(也许是专业化)的用途。甚至还有一个特征允许any concrete type


作为mentioned in the comments,你可以使用Any提供的trait object downcasting,但不能使用match

另见:

【讨论】:

  • 我的问题灵感来自我写的 Racket 解释器,其中 Match 可以在不同类型上分支。不过,Lisp 当然是动态类型的,所以在 Rust 中它是有意义的,这通常不是有用的。我觉得可能存在一些小众情况,其中动态地使用函数返回类型可能是有用的(尽管不是惯用的) - std::any 似乎主要涵盖了这个用例。谢谢!
  • 动态类型的 Lisp 是我最初困惑的来源。
  • 动态返回类型——但即便如此,您仍想对这些返回的类型进行操作。这意味着您希望能够调用一组方法;这就是特质所暗示的。它可以作为 trait 对象返回。
  • @Shepmaster 如果匹配超过一个引用,一个特征实现,试图向下转换它(let x: &Display = ...; match x {&String => ...}),并且发生在编译器不知道确切类型的某个地方怎么办?那不是很有用吗?
  • @ArtemGr 它确实知道确切的类型 — &Display ;-) 听起来你在问 trait object downcasting(请参阅 1, 2) ,由Any提供。不过,match 没有能力,因为据我所知,match 需要静态知道所有可能性。
【解决方案2】:

查看std::any::Any 和 Andrew Johnson 的链接。我认为您将能够使用Any 做一些接近您想做的事情。 fn get_type_id(&self) -> TypeId 仅在夜间构建中,所以如果你有 Rust 的稳定版本,你可能还无法使用它。

This 示例与您想要的很接近,只是使用 if let 而不是 match

我写了三个例子来演示如何实现这一点,虽然没有一个可用于match,但遗憾的是......可以找到它们并运行here。以下是我最喜欢的做法:

fn run_example_one() {
    let unknown_type = gen_rand_any();

    if let Some(string) = unknown_type.downcast_ref::<String>() {
       println!("It's a string!");
    } else if let Some(my_struct) = unknown_type.downcast_ref::<MyStruct>() {
        println!("my struct! name = {:?}", my_struct.my_name);
    } else if let Some(int) = unknown_type.downcast_ref::<i32>() {
       println!("something singed 32 bit int.");
   }
}

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 2021-10-25
    • 2023-01-26
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 2020-09-11
    相关资源
    最近更新 更多