In Rust can you associate a constant value to each enum variant and then collect those values at compile time?

huangapple go评论97阅读模式
英文:

In Rust can you associate a constant value to each enum variant and then collect those values at compile time?

问题

Here's the translated code snippet:

  1. 让我们假设我有一个枚举,并且我想以某种方式注释或关联每个变体与`&str`。例如:
  2. ```rust
  3. enum MyEnum {
  4. A, // "foo"
  5. B(String), // "bar"
  6. C(i32) // "baz"
  7. }

我还想将这些&str收集到一个数组中,如下所示:

  1. const arr: [&'static str; 3] = ["foo", "bar", "baz"];

有没有一种在编译时自动执行此操作的好方法?而不是必须单独编写常量数组?也许可以使用宏?

const fn 可以回答第一个问题,但我认为它需要#![feature(const_if_match)],如果可能的话,我更愿意使用稳定的 Rust。我也不确定它是否回答了第二个问题。我还考虑了属性宏,但我不知道是否可以在编译时将这些属性收集在一起。

  1. <details>
  2. <summary>英文:</summary>
  3. Let&#39;s say I have an enum, and I want to somehow annotate or associate each variant with a `&amp;str`. E.g.:

enum MyEnum {
A, // "foo"
B(String), // "bar"
C(i32) // "baz"
}

  1. I would also like to collect these `&amp;str`&#39;s into an array like

const arr:[&'static str; 3] = ["foo", "bar", "baz"];

  1. Is there a nice way to do this automatically at compile time? Rather than having to write out the constant array separately? Perhaps with macros?
  2. A `const fn` would answer the first part, but I believe it requires `#![feature(const_if_match)]`, and I would prefer using stable Rust if possible. I&#39;m also not sure it answered the second part. I also considered attribute macros, but I don&#39;t know how (or whether) you can collect these attributes together at compile time.
  3. </details>
  4. # 答案1
  5. **得分**: 0
  6. 您可以使用声明性宏来实现这一点:
  7. ```rust
  8. macro_rules! str_variants {
  9. { enum $enum_name:ident {
  10. $(
  11. #[str = $variant_str:literal]
  12. $variant_name:ident $variant_fields:tt
  13. ),* $(,)*
  14. } } => {
  15. enum $enum_name {
  16. $(
  17. $variant_name $variant_fields,
  18. )*
  19. }
  20. impl $enum_name {
  21. const ARR: &[&'static str] = &[
  22. $(
  23. $variant_str,
  24. )*
  25. ];
  26. }
  27. }
  28. }
  29. str_variants! { enum MyEnum {
  30. #[str = "foo"]
  31. A(),
  32. #[str = "bar"]
  33. B(String),
  34. #[str = "baz"]
  35. C(i32)
  36. } }
  37. fn main() {
  38. dbg!(MyEnum::ARR);
  39. // [src/main.rs:34] MyEnum::ARR = [
  40. // "foo",
  41. // "bar",
  42. // "baz",
  43. // ]
  44. }

您只需要在单位变体(unit variants)中使用额外的一对括号。

英文:

You can achieve this with a declarative macro:

  1. macro_rules! str_variants {
  2. { enum $enum_name:ident {
  3. $(
  4. #[str = $variant_str:literal]
  5. $variant_name:ident $variant_fields:tt
  6. ),* $(,)*
  7. } } =&gt; {
  8. enum $enum_name {
  9. $(
  10. $variant_name $variant_fields,
  11. )*
  12. }
  13. impl $enum_name {
  14. const ARR: &amp;[&amp;&#39;static str] = &amp;[
  15. $(
  16. $variant_str,
  17. )*
  18. ];
  19. }
  20. }
  21. }
  22. str_variants! { enum MyEnum {
  23. #[str = &quot;foo&quot;]
  24. A(),
  25. #[str = &quot;bar&quot;]
  26. B(String),
  27. #[str = &quot;baz&quot;]
  28. C(i32)
  29. } }
  30. fn main() {
  31. dbg!(MyEnum::ARR);
  32. // [src/main.rs:34] MyEnum::ARR = [
  33. // &quot;foo&quot;,
  34. // &quot;bar&quot;,
  35. // &quot;baz&quot;,
  36. // ]
  37. }

You just need to use an extra pair of parens with unit variants.

playground

huangapple
  • 本文由 发表于 2023年6月12日 23:19:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76458071.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定