How to define mutual recursion with closures?

前端 未结 2 1925
甜味超标
甜味超标 2021-01-20 23:18

I can do something like this:

fn func() -> (Vec, Vec) {
    let mut u = vec![0;5];
    let mut v = vec![0;5];

    fn foo(u: &mut [i         


        
2条回答
  •  醉酒成梦
    2021-01-20 23:44

    While defining mutually recursive closures works in some cases, as demonstrated in the answer by Alex Knauth, I don't think that's an approach you should usually take. It is kind of opaque, has some limitations pointed out in the other answer, and it also has a performance overhead since it uses trait objects and dynamic dispatch at runtime.

    Closures in Rust can be thought of as functions with associated structs storing the data you closed over. So a more general solution is to define your own struct storing the data you want to close over, and define methods on that struct instead of closures. For this case, the code could look like this:

    pub struct FooBar {
        pub u: Vec,
        pub v: Vec,
    }
    
    impl FooBar {
        fn new(u: Vec, v: Vec) -> Self {
            Self { u, v }
        }
    
        fn foo(&mut self, i: usize, j: usize) {
            for k in i+1..self.u.len() {
                self.u[k] += 1;
                self.bar(k, j);
            }
        }
    
        fn bar(&mut self, i: usize, j: usize) {
            for k in j+1..self.v.len() {
                self.v[k] += 1;
                self.foo(i, k);
            }
        }
    }
    
    fn main() {
        let mut x = FooBar::new(vec![0;5], vec![0;5]);
        x.foo(0, 0);
        println!("{:?}", x.u);
        println!("{:?}", x.v);
    }
    

    (Playground)

    While this can get slightly more verbose than closures, and requires a few more explicit type annotations, it's more flexible and easier to read, so I would generally prefer this approach.

提交回复
热议问题