如何在Rust中实现编译时安全、可迭代的不可变关联数组?
如何在Rust中实现编译时安全、可迭代的不可变关联数组?
我想要创建一种类似编译时不可变映射的结构,要求在编译时就能安全检查键的合法性。更宽泛地说,我需要一个具备安全键访问能力的可迭代关联数组。
我的尝试方案
方案一:使用phf的常量映射
这种方式无法保证键的访问安全性:
use phf::{phf_map}; static COUNTRIES: phf::Map<&'static str, &'static str> = phf_map! { "US" => "United States", "UK" => "United Kingdom", }; COUNTRIES.get("EU") // 无编译时错误
方案二:使用strum实现可枚举的Enum
这种方式可行,但Rust中的enum值默认是整数类型。若要为其分配其他值,需要为enum实现一个带match语句的value()函数,但这意味着每次添加新项时,都必须更新value函数,重复编写enum名称,不够理想:
use strum::IntoEnumIterator; // 0.17.1 use strum_macros::EnumIter; // 0.17.1 #[derive(Debug, EnumIter)] enum Direction { NORTH, SOUTH, EAST, WEST, } fn main() { for direction in Direction::iter() { println!("{:?}", direction); } }
方案三:在impl中使用const
这种方式支持单写实现,且对象是可安全访问的编译时常量,但尚未找到迭代它们的方法(或许可以通过过程宏实现):
struct MyType { value: &'static str } impl MyType { const ONE: MyType = MyType { value: "one" }; const TWO: MyType = MyType { value: "two" }; }
其他语言的参考实现
我有丰富的TypeScript经验,在该语言中完成这类任务非常简单:
const values = { one: "one", two: "two" // 轻松添加属性 } values.three; // 编译时错误 Object.keys(values).forEach(key => {...}) // 迭代
甚至在Java中,也可以通过带属性的enums轻松实现。
我的疑问
我知道这听起来有点像XY问题,但我认为要求一个安全、可迭代、编译时不可变的常量关联数组并非不合理。这种模式在Rust中是否可行?我找不到相关资料且实现困难,这让我觉得我的做法不符合Rust的最佳实践。如果是这样,有哪些替代方案?如果这对Rust来说是糟糕的设计模式,什么是好的替代方案?
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

