vector of closures: cannot borrow `**h` as mutable, as it is behind a `&` reference

Viewed 412

I need a vector of closures which I declared but I cannot use items of the vector due to compile error.

cannot borrow **h as mutable, as it is behind a & reference

is it possible to get the code working without dynamic memory allocation? and why h being borrowed as mutable?

fn main() {
    let hh: Vec<&dyn FnMut(&mut i32)> = vec![&|i: &mut i32| {
        *i = 10;
    }];

    let mut i = 0;
    let h = &hh[0];
    h(&mut i); // <-- cannot borrow `**h` as mutable, as it is behind a `&` reference
    println!("{}", i);
}

I have made above example works but in this case I need to declare variables for each item which looks overabundant

fn main() {
    let mut item = |i: &mut i32| {
        *i = 10;
    };
    let mut hh: Vec<&mut dyn FnMut(&mut i32)> = vec![&mut item];

    let mut i = 0;
    let h = &mut hh[0];
    h(&mut i);
    println!("{}", i);
}

is there an elegant solution?

1 Answers

If you really need the closures to be FnMut (they have persisting state), you can Box the closures in the vector.

fn main() {
    let mut state = 0; // Gets move'd to stateful closure.
    
    let mut hh: Vec<Box<dyn FnMut(&mut i32)>> = vec![
        Box::new(move |i: &mut i32| {
            state += 2; // Closure now owns `state` and it persists.
            *i = state;
        })];

    let mut i = 0;
    let     h = &mut hh[0];
    
    h(&mut i);
    println!("{}", i); // Output: 2
    
    h(&mut i);
    println!("{}", i); // Output: 4
}

Otherwise, if the closures are Fn (stateless) the code is similar to what you were trying.

fn main() {
    let hh: Vec<&dyn Fn(&mut i32)> = vec![&|i: &mut i32| {
        *i = 10;
    }];

    let mut i = 0;
    let     h = hh[0];
    h(&mut i); 
    println!("{}", i);
}
Related