将闭包传递给递归函数

时间:2014-08-18 17:28:09

标签: closures rust

我正在研究四叉树。使用闭包来确定何时应该拆分一个区域似乎是一个好主意。

pub fn split_recursively(&mut self, f: |Rect| -> bool) {
    ...
    self.children.as_mut().map(|children| {
        children.nw.split_recursively(f);
        children.ne.split_recursively(f);
        children.sw.split_recursively(f);
        children.se.split_recursively(f);
    });
}

以上就是我的尝试,但我得到了

  

错误:无法移出捕获的外部变量

     

children.se.split_recursively(F);

                      ^

四个孩子中的每一个。

然后我尝试将封装包装在RefCell

fn split_recursively(&mut self, f: &RefCell<|Rect| -> bool>)

并将其称为

let should_split = (*f.borrow_mut())(self.rect);

但Rust也不喜欢这样:

  

错误:&引用中的闭包调用

我知道如何通过将函数指针和&amp; mut传递给rng来解决这个问题(因为拆分应该部分取决于随机性),但是闭包会更优雅。有没有办法让这个与闭包一起工作?如果没有,是否可以使用未装箱的闭包?

1 个答案:

答案 0 :(得分:4)

未装箱的闭包确实有效,但它们目前是功能门控的并且增加了复杂性。

#![feature(unboxed_closures)]
use std::ops::Fn;

fn main() {
    let f = |&: x: uint| println!("Recurse {}!", x);

    recursive(&f, 0);
}

fn recursive(f: &Fn<(uint,), ()>, depth: uint) {
    if depth < 10 {
        f.call((depth,)); // Cannot be invoked like f(depth) currently.
        recursive(f, depth + 1);
    } else {
        ()
    }
}

(Rust-Playpen link)

搜索,我找到了一个简单的解决方案。只需在闭包中调用闭包:

fn main() {
    let f = |x: uint| println!("Recurse {}!", x);

    recursive(f, 0);
}

fn recursive(f: |uint| -> (), depth: uint) {
    if depth < 10 {
        f(depth);
        recursive(|x| f(x), depth + 1);
    } else {
        ()
    }
}

(Rust-Playpen link)

与未装箱的封闭相比,这会带来性能影响,但它绝对更容易阅读。你的选择。