我尝试从两个流(由迭代器表示)中找出差异以供以后分析,下面的代码工作正常,但在更新 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
s 作为参数:
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
- setter/getter :
|d| d.v1
- 二传手:
|s, d| s.v2 = d
反之亦然。
如果你想保留 update_v1
和 update_v2
函数名称,只需将它们作为包装器写入这个自动传递适当的 lambda 的新通用函数。
关于rust - 如何概括对结构字段的访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47049658/