How to create a simple, reusable local lambda

Hey all,

New to Rust, trying to understand what's the idiomatic way to do this.

fn main() {
    let mut counter = 0;
    
    let mut inc = || { counter += 1; };
    
    inc();
    counter += 2;
    inc();
}

Obviously this doesn't compile, and I understand why, but there isn't anything inherently unsafe about it that I can think of. In fact, if you were to inline the closure code, it would compile. And you obviously can write this in pretty much any other language and expect it to work.

Aside: The underlying reason seems to be that Rust always implements closures as a struct. It could do things differently. For example, here, the compiler could recognize this closure never leaves the function and inline the closure code, or it could pass all the local references as parameters to the closure code on every invocation. If it did so, the code above would satisfy the borrow checker. Of course this approach would mean invoking a closure could fail borrow checks -- the current design means creating the closure may fail borrow checks, but invoking it never does.

My question is:

Is there an elegant, idiomatic way to achieve this?

Essentially, avoid repetition in a function by creating a small local helper function. Assume counter is 4 local variables, the logic in inc is 3-4 lines and it needs to be called several times inside a single function. I would ideally not want to pass 4 mutable references as parameters every time I invoke inc, because that replaces one form of repetition with another.

Thank you!

This was recently answered here:

1 Like

Love it. That's exactly what I needed. Thank you!

Another alternative besides using Cell is to just replace the capture with an explicit &mut T argument. Assuming that there’s usually only one or at least very few variables you’d want to modify in a pattern like this that conflicts with Rust’s unique borrowing rules, this shouldn’t be too much syntactic overhead.

fn main() {
    let mut counter = 0;
    
    let inc = |c: &mut _| { *c += 1; };
    
    inc(&mut counter);
    counter += 2;
    inc(&mut counter);
}
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.