英文:
Take Ownership from retain or reference
问题
我正在编写一个Rust解析器玩具,并且想要转换一些节点,有三种可能的转换操作:删除、保留和ToTopLevel
。删除和保留是可以的,但当我遇到ToTopLevel
时,我需要克隆一个节点并将其推送到临时的Vec
中,因为它将删除节点,我想知道是否有办法获取所有权并将其直接传递给临时的Vec
。
use std::borrow::Cow;
#[derive(PartialEq, Clone)]
struct ASTNode<'a> {
value: Cow<'a, str>,
nodes: Vec<ASTNode<'a>>
}
struct Visitor<'a> {
new_node: Vec<ASTNode<'a>>
}
enum Action {
Remove,
Keep,
ToTopLevel,
}
impl<'a> Visitor<'a> {
fn some_compute_to_determinate_action(&mut self, root: &mut ASTNode<'a>) -> Action {
return Action::ToTopLevel;
}
fn visit(&mut self, root: &mut ASTNode<'a>) -> Action {
let mut children_actions: Vec<Action> = Vec::new();
for node in &mut root.nodes {
children_actions.push(self.visit(node));
}
let mut index: usize = 0;
root.nodes.retain(|node| {
index += 1;
match children_actions[index - 1] {
Action::Remove => false,
Action::Keep => true,
Action::ToTopLevel => {
// 由于它将删除节点,是否有办法获取所有权并将其推送到new_node vec中?
// 类似于:self.new_node.push(*node);
self.new_node.push(node.clone());
return false;
}
}
});
return self.some_compute_to_determinate_action(root);
}
fn push_node_to_top_level_after_visit(&mut self, root: &mut ASTNode<'a>) {
root.nodes.append(&mut self.new_node);
}
}
fn main() {
let mut root = ASTNode {
value: Cow::Borrowed("root_value"),
nodes: Vec::new()/* 假设有许多嵌套的子节点 */
};
let mut visitor = Visitor {
new_node: Vec::new()
};
visitor.visit(&mut root);
visitor.push_node_to_top_level_after_visit(&mut root);
}
英文:
I am writing a Rust parser toy, and I want to transform some nodes, there are three possible for this transform remove, keep, ToTopLevel
, remove and keep is ok, but when I encounter ToTopLevel
, I need to clone a node to push it into a temporary Vec
, since it will delete node I wonder if there is any way I can get ownership and just give it to the temporary Vec
.
use std::borrow::Cow;
#[derive(PartialEq, Clone)]
struct ASTNode<'a> {
value: Cow<'a, str>,
nodes: Vec<ASTNode<'a>>
}
struct Visitor<'a> {
new_node: Vec<ASTNode<'a>>
}
enum Action {
Remove,
Keep,
ToTopLevel,
}
impl<'a> Visitor<'a> {
fn some_compute_to_determinate_action(&mut self, root: &mut ASTNode<'a>) -> Action {
return Action::ToTopLevel;
}
fn visit(&mut self, root :&mut ASTNode<'a>) -> Action {
let mut children_actions: Vec<Action> = Vec::new();
for node in &mut root.nodes {
children_actions.push(self.visit(node));
}
let mut index: usize = 0;
root.nodes.retain(|node| {
index+=1;
match children_actions[index-1] {
Action::Remove => false,
Action::Keep => true,
Action::ToTopLevel => {
// since it would delete node, is there are any way
// i can take ownership and push it to new_node vec ?
// like : self.new_node.push(*node);
self.new_node.push(node.clone());
return false;
}
}
});
return self.some_compute_to_determinate_action(root);
}
fn push_node_to_top_level_after_visit(&mut self,root: &mut ASTNode<'a>) {
root.nodes.append(&mut self.new_node);
}
}
fn main() {
let mut root = ASTNode {
value: Cow::Borrowed("root_value"),
nodes: Vec::new()/* assume there are a a lot of nested children */
};
let mut visitor = Visitor {
new_node: Vec::new()
};
visitor.visit(&mut root);
visitor.push_node_to_top_level_after_visit(&mut root);
}
答案1
得分: 1
以下是翻译好的部分:
"However since it's possible to create an ASTNode
cheaply:
ASTNode {
value: Cow::Borrowed(""),
nodes: Vec::new()
}
what you can do is use Vec::retain_mut
and std::mem::replace
to take the "actual" ASTNode out replacing it with a dummy which you then don't keep:
root.nodes.retain_mut(|node| {
index+=1;
match children_actions[index-1] {
Action::Remove => false,
Action::Keep => true,
Action::ToTopLevel => {
self.new_node.push(std::mem::replace(node, ASTNode {
value: Cow::Borrowed(""),
nodes: Vec::new(),
}));
false
}
}
});
or if you derive(Default)
on ASTNode
, just std::mem::take
root.nodes.retain_mut(|node| {
index+=1;
match children_actions[index-1] {
Action::Remove => false,
Action::Keep => true,
Action::ToTopLevel => {
self.new_node.push(std::mem::take(node));
false
}
}
});"
英文:
There is no iterator or method which hands off the item itself (it'd need something like T -> Option<T>
as a callback, not sure why there isn't such a variant for drain
and retain
though, seems useful).
However since it's possible to create an ASTNode
cheaply:
ASTNode {
value: Cow::Borrowed(""),
nodes: Vec::new()
}
what you can do is use Vec::retain_mut
and std::mem::replace
to take the "actual" ASTNode out replacing it with a dummy which you then don't keep:
root.nodes.retain_mut(|node| {
index+=1;
match children_actions[index-1] {
Action::Remove => false,
Action::Keep => true,
Action::ToTopLevel => {
self.new_node.push(std::mem::replace(node, ASTNode {
value: Cow::Borrowed(""),
nodes: Vec::new(),
}));
false
}
}
});
or if you derive(Default)
on ASTNode
, just std::mem::take
root.nodes.retain_mut(|node| {
index+=1;
match children_actions[index-1] {
Action::Remove => false,
Action::Keep => true,
Action::ToTopLevel => {
self.new_node.push(std::mem::take(node));
false
}
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论