我正在开发一个小应用程序,我发现自己经常将许多相同的&mut
参数传递给函数。例如:
fn xyz(a: &mut A, b: &mut B) { /* ... */ }
fn bar(a: &mut A, b: &mut B, c: &mut C) { xyz(a, b); /* ... */ }
fn foo(a: &mut A, b: &mut B, c: &mut C) { bar(a, b, c); /* ... */ }
虽然在我的真实案例中,彼此之间的功能略有不同,但总共有3-4个参数。我决定做一些我认为合情合理的事情:将常见参数包装在struct
中并改为传递struct
。
struct Context {
a: A,
b: B,
c: C
}
fn xyz(c: &mut Context) { /* ... */ }
fn bar(c: &mut Context) { xyz(c); /* ... */ }
fn foo(c: &mut Context) { bar(c); /* ... */ }
如果一个函数只需要Context
个参数的子集,并且如果调用依赖于其中一个,则借用检查器会抱怨。这是一个例子:
struct Context {
f0: HashSet<String>,
f1: HashSet<String>,
}
fn bar(f1: &mut HashSet<String>) {}
fn foo(k: &str, c: &mut Context) {
c.f0.get(k).map(|_| bar(&mut c.f1));
}
error[E0500]: closure requires unique access to `c` but `c.f0` is already borrowed
--> <anon>:11:21
|
11 | c.f0.get(k).map(|_| bar(&mut c.f1));
| ---- ^^^ - - borrow ends here
| | | |
| | | borrow occurs due to use of `c` in closure
| | closure construction occurs here
| borrow occurs here
我理解错误发生的原因,但我想避免在单独传递参数时发生的所有代码重复。请注意,单独传递参数可以防止出现此问题:
fn bar(f1: &mut HashSet<String>) {}
fn foo(k: &str, f0: &mut HashSet<String>, f1: &mut HashSet<String>) {
f0.get(k).map(|_| bar(f1));
}
虽然对于这个最小的例子不正确,但使用像Context
这样的东西显着提高了我的实际代码的可读性,因为函数签名更短,代码重复也减少了。
当多个函数共享一个参数子集时,有没有办法减少代码重复?