The problem个
我正在为n-树构建预排序遍历,以这种方式给出一个闭包,以便为遍历中的每个 node 执行闭包.
我的第一个方法是:
#[derive(Debug)]
pub struct Node<T> {
value: T,
children: Vec<Node<T>>,
}
impl<T> Node<T> {
pub fn preorder<F>(&self, mut f: F)
where
F: FnMut(&Self),
{
f(self);
self.children.iter().for_each(|child| child.preorder(f));
}
}
然而,在Foreach迭代器中调用child.preorder(f)
语句时,我遇到了一个错误.
error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
--> src/lib.rs:12:62
|
7 | pub fn preorder<F>(&self, mut f: F)
| ----- captured outer variable
...
12 | self.children.iter().for_each(|child| child.preorder(f));
| ------- ^ move occurs because `f` has type `F`, which does not implement the `Copy` trait
| |
| captured by this `FnMut` closure
Solutions I found个
将preorder方法的标头更改为以下代码可以很好地编译,但它会在要使用的闭包上设置一个我根本不想要的副本.
pub fn preorder<F>(&self, mut f: F)
where
F: FnMut(&Self) + Copy,
我找到的解决闭包上必需的副本的另一种方法是使用如下所示的浸入式方法(see it in the playground):
pub struct Node<T> {
value: T,
children: Vec<Node<T>>,
}
impl<T> Node<T> {
fn preorder_immersion<F>(&self, f: &mut F)
where
F: FnMut(&Self),
{
f(self);
self.children
.iter()
.for_each(|child| child.preorder_immersion(f));
}
pub fn preorder_mut<F>(&self, mut f: F)
where
F: FnMut(&Self),
{
self.preorder_immersion(&mut f);
}
}
坦率地说,看着这一幕是痛苦的.基本上是因为它意味着每个遍历实现都有两个方法.
What I want个
如果能够在调用预订单方法时执行这样的操作,那就太好了:
let mut result = Vec::new();
node.preorder(|n| result.push(*n.value()));
我给出的最新解决方案运行良好.
My question:有没有更优雅的方式呢?我是不是遗漏了什么?或者使用沉浸式方法可以吗?