如何使用一个FnOnce封闭的参考?

问题描述 投票:0回答:1

我有一个需要递归传递一个闭合参数的函数

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,
        }
    }
}

这不起作用:

error[E0382]: use of moved value: `f`
  --> src/lib.rs:23:45
   |
22 |                 f(node.borrow().val);
   |                 - value moved here
23 |                 helper(&node.borrow().left, f);
   |                                             ^ value used here after move
   |
   = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait

error[E0382]: use of moved value: `f`
  --> src/lib.rs:24:46
   |
23 |                 helper(&node.borrow().left, f);
   |                                             - value moved here
24 |                 helper(&node.borrow().right, f);
   |                                              ^ value used here after move
   |
   = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait

如果我尝试改变从f f: F的类型f: &F我得到的编译器错误

error[E0507]: cannot move out of borrowed content
  --> src/lib.rs:22:17
   |
22 |                 f(node.borrow().val);
   |                 ^ cannot move out of borrowed content

我怎样才能解决这个问题?

我打电话这样的功能:

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);
});
rust closures
1个回答
3
投票

FnOnce是最最普通的功能限制。然而,这意味着你的代码必须为所有可能的功能,包括那些消耗他们的环境中工作。这就是为什么它被称为FnOnce:你知道它的唯一的事情是,它可以至少一次把它叫做 - 但不一定更多。里面pre_order我们只能假设是什么一切可能的F如此:它可以被调用一次。

如果您更改为FnFnMut,排除消耗他们的环境封闭,你就可以调用它多次。 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,
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.