"Closure" closing on mutable outer value?

Hi Friends!

While working through "the book" on closures that change environment I become curious whether we have a way to capture mutable outer variable which is going to change between lambda invocations. E.g.

fn main() {
    let mut a = 5;
    let mut f = | x | { x + a };
    println!("{}", f(7));
    a *= a;
    println!("{}", f(7));
}

this won't compile due to a being borrowed on lambda definition if I get it right.

Is there a way to fix it (so that first invocation prints 12 and next 32)? I feel more like "no" as it is like using variable simultaneously both in mutable and immutable flavor (and it's pretty ok if "no" - guess some other languages behave similarly) - but perhaps I miss some whimsical construction?

This can be done using Cell, which has no runtime cost.

use std::cell::Cell;

fn main() {
    let a = Cell::new(5);
    let f = | x | { x + a.get() };
    println!("{}", f(7));
    a.set(a.get() * a.get());
    println!("{}", f(7));
}

You can read more in this article.

1 Like

Alice, thanks a lot for such a quick answer - and for teaching about Cell! Couldn't imagine we are allowed to have immutable wrapper for mutable content :slight_smile: reminds of java's atomics... Will read further by link, thanks!

Rust also has atomics, which are similar to cell except that they can be used from multiple threads.

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.