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

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

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&lt;&#39;a&gt; {
    value: Cow&lt;&#39;a, str&gt;,
    nodes: Vec&lt;ASTNode&lt;&#39;a&gt;&gt;
}
struct Visitor&lt;&#39;a&gt; {
    new_node: Vec&lt;ASTNode&lt;&#39;a&gt;&gt;
}

enum Action {
    Remove,
    Keep,
    ToTopLevel,
}

impl&lt;&#39;a&gt; Visitor&lt;&#39;a&gt; {
    fn some_compute_to_determinate_action(&amp;mut self, root: &amp;mut ASTNode&lt;&#39;a&gt;) -&gt; Action {
        return Action::ToTopLevel;
    }
    fn visit(&amp;mut self, root :&amp;mut ASTNode&lt;&#39;a&gt;) -&gt; Action {
        let mut children_actions: Vec&lt;Action&gt; = Vec::new();
        for node in &amp;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 =&gt; false,
                Action::Keep =&gt; true,
                Action::ToTopLevel =&gt; {
                    // 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(&amp;mut self,root: &amp;mut ASTNode&lt;&#39;a&gt;) {
        root.nodes.append(&amp;mut self.new_node);
    }
}
fn main() {
    let mut root = ASTNode {
        value: Cow::Borrowed(&quot;root_value&quot;),
        nodes: Vec::new()/*  assume there are a a lot of nested children  */
    };
    let mut visitor = Visitor {
        new_node: Vec::new()
    };
    visitor.visit(&amp;mut root);
    visitor.push_node_to_top_level_after_visit(&amp;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 -&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:

ASTNode {
value: Cow::Borrowed(&quot;&quot;),
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 =&gt; false,
Action::Keep =&gt; true,
Action::ToTopLevel =&gt; {
self.new_node.push(std::mem::replace(node, ASTNode {
value: Cow::Borrowed(&quot;&quot;),
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 =&gt; false,
Action::Keep =&gt; true,
Action::ToTopLevel =&gt; {
self.new_node.push(std::mem::take(node));
false
}
}
});

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:

确定