【问题标题】:Pattern binding the same variable to different types sharing a trait将相同变量绑定到共享特征的不同类型的模式
【发布时间】:2020-02-21 22:03:25
【问题描述】:

我有一个关于通过特征共享某些行为的值的模式匹配的问题。

我有一个包含两个变体的枚举,每个变体的绑定值都不同,这两种类型都实现了一个特征。我试图弄清楚是否可以创建一个模式(E::VarA(x) | E::VarB(x) 形式),在其中我将两种类型绑定到一个常量,前提是我只对使用共享行为感兴趣。

一个说明性示例:Playground:

trait T {
    fn f(&self) -> usize;
}

struct A;

impl T for A {
    fn f(&self) -> usize { 1 }
}

struct B;

impl T for B {
    fn f(&self) -> usize { 2 }
}

enum E {
    VarA(A),
    VarB(B),
}

fn unwrap(e: E) -> usize {
    match e {
        E::VarA(v) | E::VarB(v) => T::f(&v)
    }
}

fn main() {
    let val = E::VarA(A{});  
    println!("{}", unwrap(val));
}

代码显然无法编译,但它表明了我的意图。有没有办法让代码工作,最好比简单地将pat1 | pat2 => ... 拆分为pat1 => ... ; pat2 => ... 更优雅?

【问题讨论】:

  • 将比赛分成不同的武器几乎是要走的路。变量绑定必须具有固定类型;它不能同时是所有可能的类型。

标签: rust pattern-matching traits


【解决方案1】:

您可以创建一个解包以匹配语句的宏。

trait T {
    fn f(&self) -> usize;
}

struct A;
impl T for A {
    fn f(&self) -> usize { 1 }
}

struct B;
impl T for B {
    fn f(&self) -> usize { 2 }
}

enum E {
    VarA(A),
    VarB(B),
}

macro_rules! unwrap {
    ($value:expr, $pattern:pat => $result:expr) => {
        match $value {
            E::VarA($pattern) => $result,
            E::VarB($pattern) => $result,
        }
    };
}

fn main() {
    let a = E::VarA(A{});
    let b = E::VarB(B{});

    println!("a:{} b:{}",
        unwrap!(a, ref sm => sm.f()),
        unwrap!(b, ref sm => sm.f()));

}

【讨论】:

    【解决方案2】:

    如果所有变体都实现了这个特征,最好的解决方案是实现整个枚举的特征 (playground)。

    相关代码:

    impl T for E {
        fn f(&self) -> usize {
            match self {
                E::VarA(x) => x.f(),
                E::VarB(x) => x.f(),
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-03
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 2015-03-24
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      相关资源
      最近更新 更多