1

I'm working on a small application where I found myself passing many of the same &mut arguments to functions over and over. Example:

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); /* ... */ }

While in my real world case the functions slightly varied in arity between each other, there were always 3-4 arguments in common. I decided to do something that I thought was sensible: wrap the common arguments in a struct and pass the struct instead.

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); /* ... */ }

If a function only needs a subset of Context's arguments and if the call depends on one of them, the borrow checker complains. Here's an example:

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


I understand why the error is happening, but I would like to avoid all the code repetition that happens when passing arguments individually. Note that passing arguments individually does prevent the issue:

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

While not true for this minimal example, using something like Context increased the readability of my real code significantly, as the function signatures were shorter and code repetition was diminished.


Is there a way to reduce code repetition when multiple functions share a subset of arguments?

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • https://play.rust-lang.org/?gist=66ba6046049adf4589f975dc646c2878&version=stable&backtrace=0 – Stargateur Jun 26 '17 at 22:51
  • @Stargateur: thanks. What if `bar` accepted a `Context` though? Is accepting separate arguments the only way to make it work? – Vittorio Romeo Jun 27 '17 at 08:04
  • Sorry I can't answer you, because I don't fully understand what you ask and I probably don't have the knowledge to answer this. Maybe you can go on the [rust chat](https://chat.stackoverflow.com/rooms/62927/rust). To ask this to experimented user. I'm still learning rust. – Stargateur Jun 27 '17 at 08:15

0 Answers0