Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何使用对FnOnce闭包的引用?_Rust_Closures - Fatal编程技术网

Rust 如何使用对FnOnce闭包的引用?

Rust 如何使用对FnOnce闭包的引用?,rust,closures,Rust,Closures,我有一个函数需要递归地传递闭包参数 use std::cell::RefCell; use std::rc::Rc; pub struct TreeNode { val: i32, left: Option<Rc<RefCell<TreeNode>>>, right: Option<Rc<RefCell<TreeNode>>>, } pub fn pre_order<F>(root:

我有一个函数需要递归地传递闭包参数

use std::cell::RefCell;
use std::rc::Rc;

pub struct TreeNode {
    val: i32,
    left: Option<Rc<RefCell<TreeNode>>>,
    right: Option<Rc<RefCell<TreeNode>>>,
}

pub fn pre_order<F>(root: Option<Rc<RefCell<TreeNode>>>, f: F)
where
    F: FnOnce(i32) -> (),
{
    helper(&root, f);

    fn helper<F>(root: &Option<Rc<RefCell<TreeNode>>>, f: F)
    where
        F: FnOnce(i32),
    {
        match root {
            Some(node) => {
                f(node.borrow().val);
                helper(&node.borrow().left, f);
                helper(&node.borrow().right, f);
            }
            None => return,
        }
    }
}
如果我尝试将
f
的类型从
f:f
更改为
f:&f
,则会出现编译器错误

错误[E0507]:无法移出借用的内容
-->src/lib.rs:22:17
|
22 | f(node.borrow().val);
|^无法移出借用的内容
我怎样才能避开这件事

我这样调用函数:

let mut node = TreeNode::new(15);
node.left = Some(Rc::new(RefCell::new(TreeNode::new(9))));

let node_option = Some(Rc::new(RefCell::new(node)));
pre_order(node_option, |x| {
    println!("{:?}", x);
});

FnOnce
是最通用的功能约束。然而,这意味着您的代码必须适用于所有可能的函数,包括那些使用其环境的函数。这就是为什么它被称为
FnOnce
:关于它,你唯一知道的是它至少可以被称为一次,但不一定是更多。在
pre_order
中,我们只能假设每个可能的
F
都是正确的:可以调用一次

如果将其更改为
Fn
FnMut
,以排除使用其环境的闭包,则可以多次调用它
FnMut
是下一个最常见的功能特征,因此最好接受这一点,而不是
Fn
,以确保您可以接受大多数功能:

pub fn pre_order<F>(root: Option<Rc<RefCell<TreeNode>>>, mut f: F)
where
    F: FnMut(i32),
{
    helper(&root, &mut f);

    fn helper<F>(root: &Option<Rc<RefCell<TreeNode>>>, f: &mut F)
    where
        F: FnMut(i32),
    {
        match root {
            Some(node) => {
                f(node.borrow().val);
                helper(&node.borrow().left, f);
                helper(&node.borrow().right, f);
            }
            None => return,
        }
    }
}
pub fn pre_order(root:Option,mut f:f)
哪里
F:FnMut(i32),
{
助手(根和mut f);
fn帮助程序(根:&选项,f:&多个f)
哪里
F:FnMut(i32),
{
匹配根{
某些(节点)=>{
f(node.borrow().val);
辅助对象(&node.borrow().left,f);
辅助对象(&node.borrow().right,f);
}
无=>返回,
}
}
}

是否有原因
F
需要属于
FnOnce()类型的
?。如果您将其更改为type
Fn()
,并使
helper()
接受
&F
,它将工作
F:FnOnce()
使闭包
F
按值移动到调用中,因此只能使用一次。您可以至少调用它一次,但不一定再调用一次。同意,我明白您的意思:)
F:FnOnce()+Copy
@cotigao
FnOnce()+Copy
不包括需要改变其环境的非移动闭包。鉴于OP示例中的函数类型没有返回值,他很可能希望它们有副作用。