Получить дискриминант перечисления без создания экземпляра

#enums #rust

#перечисления #Ржавчина

Вопрос:

Мне нужно сохранить вектор дискриминантов перечисления для сравнения:

 use std::mem;

enum Thing {
    Foo(usize),
    Bar(usize, usize),
}

let ds: Vec<mem::Discriminant<Thing>> = vec![/* ??? */];

// ...

let thing: Thing = Foo(1234);

for d in ds.iter() {
    if mem::discriminant(thing) == d {
        println!("yay");
    }
}

  

На практике, что произойдет, так это то, что макрос будет использоваться для генерации этого списка дискриминантов, чтобы соответствовать контексту в списке перечислений.

Например, у нас может быть что-то вроде этого:

 enum Thing {
    A(usize),
    B(f32),
    C(u8, u8, u8),
}

context_rule! {
    A(a) B(b) C(c) B(d) : a   b   c < d => C(b * c)
}
  

Который должен генерировать вектор дискриминантов, соответствующих vec![A, B, C, B] для проверки.

Ответ №1:

Я не думаю, что эта функциональность существует. Глядя на RFC (1 2) для дискриминантного API, он был разработан для довольно небольшого варианта использования.

При использовании перечисления ADT, которое содержит данные в некоторых вариантах, иногда желательно знать вариант, но игнорировать данные, чтобы сравнить два значения по варианту или сохранить варианты в хэш-карте, когда данные либо не хэшируются, либо неважны.

Учитывая это и ваш предполагаемый вариант использования, я бы предложил другой маршрут. Если вы хотите иметь вектор вещей, посмотрите, соответствуют ли элементы шаблону, и сделайте что-нибудь с данными; вы можете просто использовать сопоставление с шаблоном среза.

 enum Thing {
    A(usize),
    B(usize),
    C(usize, usize, usize),
}

fn main() {
    use Thing::*;

    let things = vec![A(0), B(1), C(2, 3, 4), B(5)];
    let result = match things.as_slice() {
        amp;[A(a), B(b), C(c, _, _), B(d)] if a   b   c < d => {
            C(b * c, 0, 0)
        }
        _ => todo!("add fallback")
    };

    // do something with result
}
  

Сопоставление arm выглядит очень похоже на предложенный вами макрос.

Комментарии:

1. Это сопоставление шаблонов по срезу просто потрясающе. Это такой мощный язык. Спасибо!