在 Rust 中获取两个枚举的叉积,而无需将它们全部输入出来

Get cross product of two enums in Rust without Typing them all out

提问人:Jared Smith 提问时间:9/9/2023 更新时间:9/10/2023 访问量:59

问:

例如,假设我们有两个枚举,分别代表一副标准扑克牌的等级和花色:

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum Suit {
    Spades,
    Hearts,
    Diamonds,
    Clubs,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum Rank {
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
    Ace,
}

枚举是有效的有界值集,如果希望构建所有可能对的完整套牌,我们可以将其建模为两者的笛卡尔乘积。在命令式术语中,可以想象如下

for suit in Suit {
  for rank in Rank {
    Card { suit, rank }

但是枚举不实现迭代器,这是有道理的,因为枚举可以包含任意数据类型,包括需要参数/构造的数据类型与不需要参数/构造的数据类型。我可以实现迭代器特征,或者我可以用整数元组来实现,如果我打扰的话,我可以做或可能想到的其他一些事情,问题标题中所述的问题是 AFAIK 所有这些解决方案都需要我在实现中手动输入所有 52 个变体。TryFromfor i in 0..4 { for j in 0..13 {

我知道对于静态枚举,有几种可迭代枚举宏的实现,有没有其他方法可以简单地做到这一点,而无需将它们全部键入或使用过程宏?还是我只是完全偏离了以这种方式建模一副纸牌?

蚀枚举笛 卡尔乘积

评论

3赞 Caesar 9/9/2023
例如,通过弹奏可以覆盖这一点,但对于小东西,我通常只是.然后你就可以走了.另请参阅impl Suit { fn all() -> [Self; 4] { use Self::*; [Spades, Hearts, Diamonds, Clubs] } }for suit in Suit::all() {…}
1赞 cafce25 9/9/2023
这个关于迭代枚举值的非常全面的问答是相关的。(我认为这就是凯撒想要联系的意思)。

答:

4赞 Kevin Reid 9/10/2023 #1

如前所述,有很多方法可以生成枚举迭代器,但您可能对我的库 exhaust 感兴趣,它还可以为结构(以及枚举变体中的字段值)生成笛卡尔乘积迭代器,但这不适用于这种情况):

use exhaust::Exhaust;

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Exhaust)]
enum Suit {
    Spades,
    Hearts,
    Diamonds,
    Clubs,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Exhaust)]
enum Rank {
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
    Ace,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Exhaust)]
struct Card {
    rank: Rank,
    suit: Suit,
}

fn main() {
    for c in Card::exhaust() {
        println!("{c:?}");
    }
}

指纹:

Card { rank: Two, suit: Spades }
Card { rank: Two, suit: Hearts }
Card { rank: Two, suit: Diamonds }
Card { rank: Two, suit: Clubs }
Card { rank: Three, suit: Spades }
Card { rank: Three, suit: Hearts }
Card { rank: Three, suit: Diamonds }
Card { rank: Three, suit: Clubs }
Card { rank: Four, suit: Spades }
Card { rank: Four, suit: Hearts }
...