在Rust中获得两个枚举的叉积,而无需将它们全部键入

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

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

#[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 }

然而,枚举不实现Iterator,这是有意义的,因为枚举可以包含任意数据类型,包括需要参数/构造的数据类型和不需要参数/构造的数据类型。我 * 可以 * 实现Iterator trait,或者我可以用一个整数元组实现TryFrom,然后做for i in 0..4 { for j in 0..13 {或者其他一些我可以想到的事情,如果我麻烦的话,问题的标题是AFAIK所有这些解决方案都需要我在实现中手工输入所有52个变体。
我知道对于静态枚举,有几种可迭代枚举宏的实现,有没有其他方法可以简单地做到这一点,而不需要将它们全部输入或使用过程宏?或者我只是完全偏离了基地建模这样一副牌?

9jyewag0

9jyewag01#

正如已经链接的那样,有很多方法可以生成枚举迭代器,但是你可能对我的库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 }
...

相关问题