Force capture of a variable by value while capturing others by reference

I'm a few days into learning rust and have come across a problem of this sort:

struct NoCopy<T>(T);
fn main() {
    let c = NoCopy(42);
    let i = vec![1, 2, 4].into_iter();
    let res = i.flat_map(|a| {
        (0..5).map(|b| a + b + c.0)
    });
    for x in res {
        println!("{}", x);
    }
}

This won't compile because the inner closure borrows a from the outer closure, but will outlive it. I therefore need to instruct the compiler that the inner closure should instead capture a by value. However, the move keyword will try to capture everything by value, including c. Since the type of c does not implement Copy, this fails since the outer closure is FnMut.

I also tried adding let a = a; into the inner closure, which normally forces a move (I think?), but I get the same \a` does not live long enough` error here. (Meta: Any way to escape these backticks?)

Is there any way to do this? I take it there are no C++11-style capture lists in Rust -- why not? Is there a fundamental safety issue, or is it just not yet implemented?

You can do this instead:

    let res = i.flat_map(|a| {
        let cr = &c.0;
        (0..5).map(move |b| a + b + cr)
    });

So capture c.0 by reference, and then move in the inner closure.

Actually, I can even do:

    let res = i.flat_map(|a| {
        let cr = &c;
        (0..5).map(move |b| a + b + cr.0)
    });

which is more generally useful (e. g. for me, c is a HashMap and I perform lookups in the inner lambda.) Still, quite a hoop to jump through.

Yeah, indeed it doesn't matter since you're creating an immutable reference and those are fine to move (actually, copy) around.

If you squint, that's your capture list specification :slight_smile:.

I guess that is a way to look at it :smile: especially since I don't even need to change the name, let c = &c; works just as well. It's a bit verbose, but, oh well. Thanks!

Yup, you can shadow the binding.

By the way, the need to sometimes borrow some of the environment and move the rest was discussed a bit yesterday here: Basic question about closures, move, Vec<T> - #8 by bugaevc

I always seem to run into those immediately ..