【问题标题】:are succinct struct initializers possible是否可以使用简洁的结构初始化器
【发布时间】:2020-11-13 13:47:18
【问题描述】:

说我有

struct S1{
  name:&'s str,
  start : u8,
  end : u8,
}

我想把它们做成一个数组

在 C 和 c++ 中我可以去(一个 v 通用模式)

  S1 arr[] ={
     {"foo",1,2},
     {"bar",4,5},
  }

看来这一定是生锈了

  let arr = [
     S1{name:"foo", start:1, end: 2},
     S1{name:"bar", start:4, end: 5},
    ]

这里的问题是 a) 输入很多 b) 表中的信息被重复的结构和字段名称所淹没。

我发现我可以使用元组

let arr = [("foo",1,2),("bar",3,4)]

但我失去了按名称引用字段的能力。

我错过了什么吗?也许是一个辅助宏? (写 rust 的 3 天后,如果出现常见问题或愚蠢,请致歉)

【问题讨论】:

  • 您可以编写自己的 macros,但如果这是定义一次且永不更改的静态数据(在您的软件的每次执行中),那么我建议将这些原始数据移动到文本中文件,然后编写一个函数将它们读入 Vec.隐藏 Vec(使用modules)使其不能被可变访问,并且您应该像使用硬编码数组一样安全。但我对 Rust 也很陌生,所以希望一些专家加入。

标签: rust


【解决方案1】:

您可以选择使用构造函数代替,这将等效于元组版本,但由于函数调用而具有额外的前缀:

let arr = [S1::new("foo",1,2), S1::new("bar",3,4)]

如果您想模拟元组数组/C++ 括号并且除了数组中的初始值之外什么都没有,您可以使用宏将参数元组/组列表扩展为构造函数调用:

let arr = expand![
    ("foo", 1, 2), 
    ("bar", 3, 4), 
    ("baz", 5, 6), 
    ("qux", 7, 8)
];

expand!声明如下:

macro_rules! expand {
    ( $( ($name:expr, $start:expr, $end:expr) ),* ) => {
        [ $( S1 { name: $name, start: $start, end: $end } ),* ]
    }
}

如果您想使用大括号而不是括号来对参数进行分组,只需将匹配器中包含$name:expr, $start:expr, $end:expr 的括号替换为大括号即可。请注意,您可以使用大括号、圆括号或方括号调用宏,因此您可以使其看起来与 C++ 版本完全相同,除非宏调用:

let arr = expand! {
    {"foo", 1, 2}, 
    {"bar", 3, 4}, 
    {"baz", 5, 6}, 
    {"qux", 7, 8}
};

Playground

【讨论】:

  • ty,天哪,我有很多东西要学(v 经验丰富的 c++ 开发人员决定尝试 rust 进行一个不平凡的项目——为了好玩)。那个宏的东西看起来很关键(与“真正的程序员不再做宏”的 C++ 不同)
【解决方案2】:

我同意写出整个列表可能很笨拙。 我发现我在测试中只有这种情况。 在那种情况下,我所做的是编写一个很小的本地函数 在列表上方并使用它。如果我最终在一个 很少测试,我可能会将其移至测试模块范围。 无论哪种方式,因为我们已经控制了函数的范围 使用一个很短的名字并没有那么糟糕。

pub fn main() {
    fn s(name: &str, start: u8, end: u8) -> S1 {
        S1 { name, start, end }
    }
    let arr = [s("foo", 1, 2), s("bar", 4, 5)];
    println!("arr={:?}", arr2)
}

您可以在playground 中查看完整的工作示例。

【讨论】:

    【解决方案3】:

    这就是我最终要做的。

    使用@EvilTak 建议的宏并混入https://docs.rs/phf/0.8.0/phf/

    我知道了

    macro_rules! expand {
        ( $( ($name:expr, $start:expr, $end:expr) ),* ) => {
            [ $( RegDef { name: $name, start: $start, end: $end } ),* ]
        }
    }
    
    #[derive(Debug)]
    struct RegDef{
        name:&'static str,
        start: usize,
        end: usize
    }
    
    static REGDEF_MAP: phf::Map<&'static str, &[RegDef]> = phf_map!{
        "rkcs" => &expand![
            ("err", 15, 16),
            ("he", 14, 15),
            ("scp", 13, 14),
            ("inhib", 11, 12),
            ("fmt", 10, 11),
            ("sse", 8, 9),
            ("rdy", 7, 8),
            ("ide", 6, 7),
            ("mex", 4, 6),
            ("func", 1, 4),
            ("go", 0, 1)
        ],
        "rker" => &expand![
            ("dre", 15, 16),
            ("ovr", 14, 15),
            ("wlo", 13, 14),
            ("ske", 12, 13),
            ("pge", 11, 12),
            ("nxm", 10, 11),
            ("dlt", 9, 10),
            ("tme", 8, 9),
            ("nxd", 7, 8),
            ("nxc", 6, 7),
            ("nxs", 5, 6),
            ("cse", 1, 2),
            ("wce", 0, 1)
        ],
        "rkds" => &expand![
            ("drid", 13, 16),
            ("pwr", 12, 13),
            ("rk05", 11, 12),
            ("dru", 10, 11),
            ("seeki", 9, 10),
            ("scok", 8, 9),
            ("rdy", 7, 8),
            ("ardy", 6, 7),
            ("wp", 5, 6),
            ("scsa", 4, 5),
            ("sc", 0, 4)
        ],
        "rkda" => &expand![
            ("drv", 13, 16),
            ("cyl", 5,13),
            ("sur", 4, 5),
            ("sec", 0, 4)
        ],
    
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-08
      • 2019-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-07
      相关资源
      最近更新 更多