Reusing a closure

I got stuck on another Rust closure puzzle today. What I'm trying to do boils down to this, which won't compile:

fn main() {
    let buffers: [[u8; 2]; 2] = [[1, 2], [3, 4]];
    
    let mut mysum: u8 = 0;

    let my_chksum = |c| {
        mysum += c;
    };
    for buf in buffers {
        generic_sum(&buf, my_chksum);
    }
    println!("My checksum is {}", mysum); // Expecting 10
}

fn generic_sum<F>(buf: &[u8], mut summer: F) where
    F: FnMut(u8) {
    
    for c in buf {
        summer(*c);
    }
}

This gives me the error

closure cannot be moved more than once as it is not Copy due to moving the variable mysum out of its environment

I shouldn't be actually moving it, since it's FnMut not FnOnce, right?

I can move the closure definition inside the for buf in buffers loop, which seems to work. Is that efficient? Is there a better way to solve this?

I shouldn't be actually moving it, since it's FnMut not FnOnce, right?

it isn't necessary to move a FnMut to call it, but in your code you are moving it, because you're passing it to generic_sum by value.

A reasonable fix here is to change the call from generic_sum(&buf, my_chksum); to generic_sum(&buf, &mut my_chksum); so that the function is not moved from main to generic_sum.

(You don't need to change generic_sum to do this, because FnMut is implemented for all &mut F where F: FnMut.)

6 Likes

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.