这里有很多关于 Rust 中的自引用结构的问题,我想我已经阅读了所有这些问题,但我仍然无法理解这些问题。在 Rust 中处理自引用结构有哪些设计模式?我会列出我的想法,以便其他人可以告诉我哪里出错了(我有一种感觉,它是在开始时)。
当我学习一门新语言时,我尝试实现相同的游戏,而对于 Rust,我遇到了这个问题:我们有资源,其中一些可以从其他资源中制作。(假设它们形成一个 DAG。)
我对它进行建模的天真尝试是这样的:
struct Resource {
name: String,
production_cost: HashMap<&Resource, i32>,
// other data
}
Run Code Online (Sandbox Code Playgroud)
我们需要一个引用的生命周期注解,所以它变成Resource<'a>
了一个HashMap<&'a Resource, i32>
.
Vec<Resource>
这种形式的A是不切实际的(不可能?)构建,所以另一个尝试是上升一个级别:
struct Resource {
name: String,
// other data
}
struct ResourceConfig {
resources: Vec<Resource>,
resource_costs: HashMap<&Resource, HashMap<&Resource, i32>>,
}
Run Code Online (Sandbox Code Playgroud)
我也想不出构造其中一个的方法。我能想到的接下来的两个选项是:
所以最终结果(2)看起来像:
type RIndex = usize;
type ResourceSet = HashMap<RIndex, i32>;
struct Resource {
name: String,
// other data
}
struct ResourceConfig {
resources: Vec<Resource>,
resource_costs: HashMap<RIndex, ResourceSet>,
}
Run Code Online (Sandbox Code Playgroud)
其余的代码只是传递一堆RIndex
“es”(并保留一个&ResourceConfig
引用来进行转换)。我可以RIndex
以击键为代价从类型别名升级到类型安全的新类型(可能值得吗?),但最后我觉得我只是在做我自己的指针管理——而不是担心无效/空我担心RIndex
超出范围。
我在这里缺少什么?(不安全的代码?)
在 C++ 中,我会做类似的事情:
class Resource {
std::string name;
std::unordered_map<Resource*, int> production_cost;
// Probably wrap the unordered_map in its own class, maybe with a Resource reference, etc.
}
Run Code Online (Sandbox Code Playgroud)
(当然,我会失去生命周期保证,但资源都将位于同一对象中的某个地方,因此工作起来并不难。)
\n\n将索引传递给主向量。
\n
您正在描述一个 arena \xe2\x80\x93 ,一个可以通过索引相互链接的结构向量。有一些不错的包可以让你做到这一点,并提供一些编译时检查。
\n对于您的情况,我们可以更进一步\xe2\x80\x93,因为您不需要在创建资源类型后销毁该资源类型,所有资源都可以在相同的生命周期内生存(一旦创建) 。因此,理论上您应该能够让竞技场中的项目相互引用。typed-arena可以让你做到这一点!
\nuse typed_arena::Arena;\n\nfn main() {\n let resources = Arena::<Resource>::default();\n\n let iron = resources.alloc(Resource {\n name: "iron".to_string(),\n cost: vec![],\n });\n let water = resources.alloc(Resource {\n name: "water".to_string(),\n cost: vec![],\n });\n let rust = resources.alloc(Resource {\n name: "rust".to_string(),\n cost: vec![iron, water],\n });\n\n println!("{iron:?}");\n println!("{water:?}");\n println!("{rust:?}");\n}\n\n#[derive(Debug)]\nstruct Resource<\'a> {\n name: String,\n cost: Vec<&\'a Resource<\'a>>,\n}\n
Run Code Online (Sandbox Code Playgroud)\nResource { name: "iron", cost: [] }\nResource { name: "water", cost: [] }\nResource { name: "rust", cost: [Resource { name: "iron", cost: [] }, Resource { name: "water", cost: [] }] }\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
3422 次 |
最近记录: |