我尝试找到两个流(由迭代器表示)的差异以进行后续分析,下面的代码工作正常,但是在update_v?
函数中更新值时看起来有点难看并且容易出错(复制粘贴!)。假设来源很重要,有什么办法可以概括它?
struct Data {};
struct S {
v1: Option<Data>,
v2: Option<Data>
}
...
fn update_v1(diffs: &mut HashMap<u64, Data>, key: u64, data: Data) {
match diffs.entry(key) {
Entry::Vacant(v) => {
let variant = S {
v1: Some(data),
v2: None
};
v.insert(variant);
},
Entry::Occupied(e) => {
let new_variant = Some(data);
if e.get().v2 == new_variant {
e.remove();
} else {
let existing = e.into_mut();
existing.v1 = new_variant;
}
}
}
}
fn update_v2(diffs: &mut HashMap<u64, Data>, key: u64, data: Data) {
match diffs.entry(key) {
Entry::Vacant(v) => {
let variant = S {
v2: Some(data),
v1: None
};
v.insert(variant);
},
Entry::Occupied(e) => {
let new_variant = Some(data);
if e.get().v1 == new_variant {
e.remove();
} else {
let existing = e.into_mut();
existing.v2 = new_variant;
}
}
}
}
最佳答案
代替为每个字段编写一个函数,而是接收一对Fn
作为参数:
fn(&S) -> Option<Data>
,可以用来代替这种情况if e.get().v1 == new_variant { /* ... */ }
有了这个
if getter(e.get()) == new_variant { /* ... */ }
fn(&mut S, Option<Data>) -> ()
,它将替换existing.v2 = new_variant;
和
setter(&mut existing, new_variant);
然后,在调用站点上,您会传递几个lambda
|d| d.v1
|s, d| s.v2 = d
或反之亦然。
而且,如果要保留
update_v1
和update_v2
函数名称,只需将它们作为包装器写入到此新的通用函数即可,该函数会自动传递适当的lambda。关于rust - 如何概括对结构域的访问?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47049658/