将常用函数参数打包到struct中 - 减少重复,打击借用检查器

时间:2017-06-26 22:21:21

标签: rust borrow-checker

我正在开发一个小应用程序,我发现自己经常将许多相同的&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

on rust playground

我理解错误发生的原因,但我想避免在单独传递参数时发生的所有代码重复。请注意,单独传递参数可以防止出现此问题:

fn bar(f1: &mut HashSet<String>) {}

fn foo(k: &str, f0: &mut HashSet<String>, f1: &mut HashSet<String>) {
    f0.get(k).map(|_| bar(f1));
}

on rust playground

虽然对于这个最小的例子不正确,但使用像Context这样的东西显着提高了我的实际代码的可读性,因为函数签名更短,代码重复也减少了。

当多个函数共享一个参数子集时,有没有办法减少代码重复?

0 个答案:

没有答案