Rust 使用模式匹配在结构字段之间进行选择
背景: 我正在尝试在Rust中实现一个简单的虚拟机。现在,我正在开发一个寄存器库,它支持字符串和整数的空间。 RegisterBank结构如下所示:Rust 使用模式匹配在结构字段之间进行选择,rust,Rust,背景: 我正在尝试在Rust中实现一个简单的虚拟机。现在,我正在开发一个寄存器库,它支持字符串和整数的空间。 RegisterBank结构如下所示: pub struct RegisterBank { int_registers: Vec<i32>, str_registers: Vec<String>, } 还有我想学的模式匹配 pub fn load(self, register: SomeMatchableType) { match reg
pub struct RegisterBank {
int_registers: Vec<i32>,
str_registers: Vec<String>,
}
还有我想学的模式匹配
pub fn load(self, register: SomeMatchableType) {
match register { ... }
}
因为为两个非常相似的任务使用一个函数似乎很好,所以我尝试了以下方法:
enum OperandType {
Number(i32),
Word(String),
}
fn main() {
let mut rb = RegisterBank::new();
rb.store(2, 5);
rb.store(2, "foo".to_owned());
let intreg: i32 = rb.load(2);
let strreg: String = rb.load(2);
assert!(intreg == 5);
assert!(strreg == "foo");
}
然后有一个类似于pub-fn-loadself,register:operantype的函数,它匹配register并返回一个字符串或&str,根据其操作数类型返回任意值或整数
问题:
目前,i32和String的实现停留在两个独立的函数上,这很好。因为我已经为fn-store&mut-self、register:usize、value:operantype完成了这项工作,所以对于fn-loadself、register:?,这应该是可能的???也我最大的问题是设计这样一个函数,该函数根据操作数类型枚举或其他(如果有人有聪明的想法)将两个任务组合成一个模式匹配
基本上,解决方案应该做到:
根据输入参数确定要选择的寄存器int\U寄存器或str\U寄存器
获取寄存器的内容
还它
加载模式不可能匹配输入参数,因为按照定义,它根本没有可以匹配的模式。您似乎真正在寻找的是一种通过返回类型使load成为泛型的方法——您很幸运,因为生锈实际上使这成为可能
在casei32和String中,您需要创建一个泛型特征,并为所涵盖的类型提供实现:
类似的技术可以用来摆脱笨重的操作数类型包装器。定义一个StoreRegister特性,该特性为RegisterBank提供存储,并使用i32和字符串值类型执行具体存储:
trait StoreToRegister<T> {
fn store(&mut self, register: usize, value: T);
}
impl StoreToRegister<i32> for RegisterBank {
fn store(&mut self, register: usize, n: i32) {
self.int_registers[register] = n;
}
}
impl StoreToRegister<String> for RegisterBank {
fn store(&mut self, register: usize, s: String) {
self.str_registers[register] = s;
}
}
这两个特性可以合并为一个寄存器存储特性,该特性同时提供加载和保存。完整的代码。您可以创建一个枚举注册表类型{numberUser Size,Wordusize}顺便说一句,这与您的问题没有任何关系,但我认为如果您将操作数类型重命名为仅操作数,您的代码可能会看起来更地道
let intreg: i32 = rb.load(2); // or, let intreg = rb.load::<i32>(2);
let strreg: String = rb.load(2);
trait StoreToRegister<T> {
fn store(&mut self, register: usize, value: T);
}
impl StoreToRegister<i32> for RegisterBank {
fn store(&mut self, register: usize, n: i32) {
self.int_registers[register] = n;
}
}
impl StoreToRegister<String> for RegisterBank {
fn store(&mut self, register: usize, s: String) {
self.str_registers[register] = s;
}
}
fn main() {
let mut rb = RegisterBank::new();
rb.store(2, 5);
rb.store(2, "foo".to_owned());
let intreg: i32 = rb.load(2);
let strreg: String = rb.load(2);
assert!(intreg == 5);
assert!(strreg == "foo");
}