如何定义带有闭包的相互递归?

2023-12-10

我可以做这样的事情:

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

    fn foo(u: &mut [i32], v: &mut [i32], i: usize, j: usize) {
        for k in i+1..u.len() {
            u[k] += 1;
            bar(u, v, k, j);
        }
    }
    fn bar(u: &mut [i32], v: &mut [i32], i: usize, j: usize) {
        for k in j+1..v.len() {
            v[k] += 1;
            foo(u, v, i, k);
        }
    }
    foo(&mut u, &mut v, 0, 0);
    (u,v)
}

fn main() {
    let (u,v) = func();
    println!("{:?}", u);
    println!("{:?}", v);
}

但我更愿意做这样的事情:

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

    let foo = |i, j| {
        for k in i+1..u.len() {
            u[k] += 1;
            bar(k, j);
        }
    };
    let bar = |i, j| {
        for k in j+1..v.len() {
            v[k] += 1;
            foo(i, k);
        }
    };
    foo(0, 0);
    (u,v)
}

fn main() {
    let (u,v) = func();
    println!("{:?}", u);
    println!("{:?}", v);
}

第二个示例未编译并出现错误:未解析的名称bar。 在我的任务中,我可以通过一次递归来完成它,但看起来不太清楚。 有人还有其他建议吗?


我有一个相互递归闭包的解决方案,但它不适用于多个可变借用,因此我无法将其扩展到您的示例。

有一种方法可以使用定义相互递归闭包,使用类似于这个答案进行单次递归。您可以将闭包放在一个结构中,其中每个闭包都借用该结构作为额外的参数。

fn func(n: u32) -> bool {
    struct EvenOdd<'a> {
        even: &'a Fn(u32, &EvenOdd<'a>) -> bool,
        odd: &'a Fn(u32, &EvenOdd<'a>) -> bool
    }
    let evenodd = EvenOdd {
        even: &|n, evenodd| {
            if n == 0 {
                true
            } else {
                (evenodd.odd)(n - 1, evenodd)
            }
        },
        odd: &|n, evenodd| {
            if n == 0 {
                false
            } else {
                (evenodd.even)(n - 1, evenodd)
            }
        }
    };
    (evenodd.even)(n, &evenodd)
}

fn main() {
    println!("{}", func(5));
    println!("{}", func(6));
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何定义带有闭包的相互递归? 的相关文章

随机推荐