从保留或引用中获取所有权

huangapple go评论109阅读模式
英文:

Take Ownership from retain or reference

问题

我正在编写一个Rust解析器玩具,并且想要转换一些节点,有三种可能的转换操作:删除、保留和ToTopLevel。删除和保留是可以的,但当我遇到ToTopLevel时,我需要克隆一个节点并将其推送到临时的Vec中,因为它将删除节点,我想知道是否有办法获取所有权并将其直接传递给临时的Vec

  1. use std::borrow::Cow;
  2. #[derive(PartialEq, Clone)]
  3. struct ASTNode<'a> {
  4. value: Cow<'a, str>,
  5. nodes: Vec<ASTNode<'a>>
  6. }
  7. struct Visitor<'a> {
  8. new_node: Vec<ASTNode<'a>>
  9. }
  10. enum Action {
  11. Remove,
  12. Keep,
  13. ToTopLevel,
  14. }
  15. impl<'a> Visitor<'a> {
  16. fn some_compute_to_determinate_action(&mut self, root: &mut ASTNode<'a>) -> Action {
  17. return Action::ToTopLevel;
  18. }
  19. fn visit(&mut self, root: &mut ASTNode<'a>) -> Action {
  20. let mut children_actions: Vec<Action> = Vec::new();
  21. for node in &mut root.nodes {
  22. children_actions.push(self.visit(node));
  23. }
  24. let mut index: usize = 0;
  25. root.nodes.retain(|node| {
  26. index += 1;
  27. match children_actions[index - 1] {
  28. Action::Remove => false,
  29. Action::Keep => true,
  30. Action::ToTopLevel => {
  31. // 由于它将删除节点,是否有办法获取所有权并将其推送到new_node vec中?
  32. // 类似于:self.new_node.push(*node);
  33. self.new_node.push(node.clone());
  34. return false;
  35. }
  36. }
  37. });
  38. return self.some_compute_to_determinate_action(root);
  39. }
  40. fn push_node_to_top_level_after_visit(&mut self, root: &mut ASTNode<'a>) {
  41. root.nodes.append(&mut self.new_node);
  42. }
  43. }
  44. fn main() {
  45. let mut root = ASTNode {
  46. value: Cow::Borrowed("root_value"),
  47. nodes: Vec::new()/* 假设有许多嵌套的子节点 */
  48. };
  49. let mut visitor = Visitor {
  50. new_node: Vec::new()
  51. };
  52. visitor.visit(&mut root);
  53. visitor.push_node_to_top_level_after_visit(&mut root);
  54. }
英文:

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.

  1. use std::borrow::Cow;
  2. #[derive(PartialEq, Clone)]
  3. struct ASTNode&lt;&#39;a&gt; {
  4. value: Cow&lt;&#39;a, str&gt;,
  5. nodes: Vec&lt;ASTNode&lt;&#39;a&gt;&gt;
  6. }
  7. struct Visitor&lt;&#39;a&gt; {
  8. new_node: Vec&lt;ASTNode&lt;&#39;a&gt;&gt;
  9. }
  10. enum Action {
  11. Remove,
  12. Keep,
  13. ToTopLevel,
  14. }
  15. impl&lt;&#39;a&gt; Visitor&lt;&#39;a&gt; {
  16. fn some_compute_to_determinate_action(&amp;mut self, root: &amp;mut ASTNode&lt;&#39;a&gt;) -&gt; Action {
  17. return Action::ToTopLevel;
  18. }
  19. fn visit(&amp;mut self, root :&amp;mut ASTNode&lt;&#39;a&gt;) -&gt; Action {
  20. let mut children_actions: Vec&lt;Action&gt; = Vec::new();
  21. for node in &amp;mut root.nodes {
  22. children_actions.push(self.visit(node));
  23. }
  24. let mut index: usize = 0;
  25. root.nodes.retain(|node| {
  26. index+=1;
  27. match children_actions[index-1] {
  28. Action::Remove =&gt; false,
  29. Action::Keep =&gt; true,
  30. Action::ToTopLevel =&gt; {
  31. // since it would delete node, is there are any way
  32. // i can take ownership and push it to new_node vec ?
  33. // like : self.new_node.push(*node);
  34. self.new_node.push(node.clone());
  35. return false;
  36. }
  37. }
  38. });
  39. return self.some_compute_to_determinate_action(root);
  40. }
  41. fn push_node_to_top_level_after_visit(&amp;mut self,root: &amp;mut ASTNode&lt;&#39;a&gt;) {
  42. root.nodes.append(&amp;mut self.new_node);
  43. }
  44. }
  45. fn main() {
  46. let mut root = ASTNode {
  47. value: Cow::Borrowed(&quot;root_value&quot;),
  48. nodes: Vec::new()/* assume there are a a lot of nested children */
  49. };
  50. let mut visitor = Visitor {
  51. new_node: Vec::new()
  52. };
  53. visitor.visit(&amp;mut root);
  54. visitor.push_node_to_top_level_after_visit(&amp;mut root);
  55. }

答案1

得分: 1

以下是翻译好的部分:

"However since it's possible to create an ASTNode cheaply:

  1. ASTNode {
  2. value: Cow::Borrowed(""),
  3. nodes: Vec::new()
  4. }

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:

  1. root.nodes.retain_mut(|node| {
  2. index+=1;
  3. match children_actions[index-1] {
  4. Action::Remove => false,
  5. Action::Keep => true,
  6. Action::ToTopLevel => {
  7. self.new_node.push(std::mem::replace(node, ASTNode {
  8. value: Cow::Borrowed(""),
  9. nodes: Vec::new(),
  10. }));
  11. false
  12. }
  13. }
  14. });

or if you derive(Default) on ASTNode, just std::mem::take

  1. root.nodes.retain_mut(|node| {
  2. index+=1;
  3. match children_actions[index-1] {
  4. Action::Remove => false,
  5. Action::Keep => true,
  6. Action::ToTopLevel => {
  7. self.new_node.push(std::mem::take(node));
  8. false
  9. }
  10. }
  11. });"
英文:

There is no iterator or method which hands off the item itself (it'd need something like T -&gt; Option&lt;T&gt; 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:

  1. ASTNode {
  2. value: Cow::Borrowed(&quot;&quot;),
  3. nodes: Vec::new()
  4. }

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:

  1. root.nodes.retain_mut(|node| {
  2. index+=1;
  3. match children_actions[index-1] {
  4. Action::Remove =&gt; false,
  5. Action::Keep =&gt; true,
  6. Action::ToTopLevel =&gt; {
  7. self.new_node.push(std::mem::replace(node, ASTNode {
  8. value: Cow::Borrowed(&quot;&quot;),
  9. nodes: Vec::new(),
  10. }));
  11. false
  12. }
  13. }
  14. });

or if you derive(Default) on ASTNode, just std::mem::take

  1. root.nodes.retain_mut(|node| {
  2. index+=1;
  3. match children_actions[index-1] {
  4. Action::Remove =&gt; false,
  5. Action::Keep =&gt; true,
  6. Action::ToTopLevel =&gt; {
  7. self.new_node.push(std::mem::take(node));
  8. false
  9. }
  10. }
  11. });

huangapple
  • 本文由 发表于 2023年7月23日 23:00:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76748915.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定