在Rust中使用“match”和嵌套的“enum”

gwbalxhn  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(103)

假设我有一个枚举,它包含某种嵌套结构。有没有一种方法可以建模,这样Rust编译器可以在使用match时提供有用的检查,同时避免冗长的match语句。例如,是否可以沿着以下路线沿着进行,或者如何更好地模拟这种情况?

enum Group {
    TeamA1,
    TeamA2,
    TeamB1,
    TeamB2,
    TeamC1
}

fn is_team_a(group: Group) -> bool {
    todo!()
}
fn is_team_b(group: Group) -> bool {
    todo!()
}
fn is_team_c(group: Group) -> bool {
    todo!()
}

fn hi(group::Group) -> String {
    match group {
        is_team_a => "hi team A".to_string(),
        is_team_b => "hi team B".to_string(),
        is_team_c => "hi team C".to_string()
    }
}
kjthegm6

kjthegm61#

有很多方法可以解决这个问题;你选择哪一个当然部分是你的设计决定,部分取决于使用情况。
我想到了几个选择:

#[derive(Clone, Copy)]
enum Group {
    TeamA1,
    TeamA2,
    TeamB1,
    TeamB2,
    TeamC1,
}

fn is_team_a(group: Group) -> bool {
    todo!()
}
fn is_team_b(group: Group) -> bool {
    todo!()
}
fn is_team_c(group: Group) -> bool {
    todo!()
}

fn hi(group: Group) -> String {
    match group {
        _ if is_team_a(group) => "hi team A".to_string(),
        _ if is_team_b(group) => "hi team B".to_string(),
        _ if is_team_c(group) => "hi team C".to_string(),
        _ => unreachable!(),
    }
}

积极的一面是,这段代码与您的示例非常接近。
然而,负面影响是:

  • 不能保证组不能同时属于A组和B组
  • 需要unreachable!()分支,因为无法证明基于if的匹配是穷举的

如果这是我的代码,我会通过创建一个单独的Team枚举来解决这个问题:

#[derive(Clone, Copy)]
enum Group {
    TeamA1,
    TeamA2,
    TeamB1,
    TeamB2,
    TeamC1,
}

#[derive(Clone, Copy)]
enum Team {
    TeamA,
    TeamB,
    TeamC,
}

impl Group {
    fn get_team(self) -> Team {
        use Group::*;
        use Team::*;
        match self {
            TeamA1 | TeamA2 => TeamA,
            TeamB1 | TeamB2 => TeamB,
            TeamC1 => TeamC,
        }
    }
}

fn hi(group: Group) -> String {
    match group.get_team() {
        Team::TeamA => "hi team A".to_string(),
        Team::TeamB => "hi team B".to_string(),
        Team::TeamC => "hi team C".to_string(),
    }
}

或者将两者合并结合起来:

#[derive(Clone, Copy)]
enum Group {
    TeamA(u32),
    TeamB(u32),
    TeamC(u32),
}

fn hi(group: Group) -> String {
    match group {
        Group::TeamA(_) => "hi team A".to_string(),
        Group::TeamB(_) => "hi team B".to_string(),
        Group::TeamC(_) => "hi team C".to_string(),
    }
}

相关问题