如何用闭包定义相互递归? [英] How to define mutual recursion with closures?

查看:53
本文介绍了如何用闭包定义相互递归?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以这样做:

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);
}

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

but I would prefer to do something like this:

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);
}

第二个例子没有编译,错误:unresolved name bar.在我的任务中,我可以通过一次递归来完成,但看起来不太清楚.有人有其他建议吗?

The second example doesn't compile with the error: unresolved name bar. In my task I can do it through one recursion, but it will not look clear. Does anyone have any other suggestions?

推荐答案

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

I have a solution for mutually recursive closures, but it doesn't work with multiple mutable borrows, so I couldn't extend it to your example.

>

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

There is a way to use define mutually recursive closures, using an approach similar to how this answer does single recursion. You can put the closures together into a struct, where each of them takes a borrow of that struct as an extra argument.

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));
}

这篇关于如何用闭包定义相互递归?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆