How to do recursive closure and mutate the captured env

fn a(mut nums: Vec<i32>){
    let x = |i|{
            if i < 0{return}
            num.push(i);
           x(i-1)
    }
    x(10);
}

The easiest way to change this code is probably to just define an fn, giving the environment as an argument, and then you can wrap that in a closure if you like. E.g.

fn a(mut nums: Vec<i32>) {
    let mut x = |i| {
        fn rec(i: i32, nums: &mut Vec<i32>) {
            if i < 0 {
                return;
            }
            nums.push(i);
            rec(i - 1, nums)
        }
        rec(i, &mut nums)
    };
    x(10);
}

Since you're coming from the IRLO thread where you had given additional information in the form of the following text description

The code example you provided here doesn't work directly with Fn-closures either, because x isn't even in scope where you're trying to recursively call it.

error[E0425]: cannot find function `x` in this scope
 --> src/lib.rs:5:12
  |
5 |            x(i-1)
  |            ^ not found in this scope

Rust Playground

It sounds like you might have done an approach of recursion involving structs (which makes sense because otherwise getting the signatures right can be impossible even with Box<dyn ..> stuff), if you want feedback on how to adapt that to FnMut setttings, feel free to share that, too.

You might also want to tell us more about what you are trying to achieve in general; of course the toy example you gave doesn't need either of a closure or recursion, a simple loop could do the same.

1 Like
fn a(mut nums: Vec<i32>){
    struct rec<'a>{
        f : &'a dyn Fn(&rec, i32, &mut Vec<i32>)
    }
    let x = rec{
        f : &|x, i, num|{
            if i < 0{return;}
            num.push(i);
            (x.f)(x, i-1, num);
    }};
    (x.f)(&x, 10, &mut nums);
}
fn main(){
    a(vec![1, 1, 1]);
}

I can do it like this, but I wonder how to do it with FnMut

I guess that really is impossible with FnMut. The problem is that there's no way the compiler could be told that "the data this closure captures mustn't be in-use while you use this argument to the closure". And if the argument x of the |x, i, num| closure was callable while also still having (mutable) access to something the closure captured, then you're quickly able to create aliased mutable access.

The best I could come up with to still utilize closure capturing (i.e. for example not have to mention the Vec in the definition of the rec struct) would be to keep it a Fn and wrap some captures in RefCells or so. E.g. in this playground the RefCell prevents the possibility of aliased mutable access to nums at run-time.

1 Like