rust - Storing trait objects in structs -


i'm working on parser has bunch of different nodes (~6 node kinds right now, more later) , i'm bit lost how interact node items (all nodes implement node trait) need use box<node> everywhere.

listnode looks like:

pub struct listnode {     kind: nodekind,     position: usize,     pub nodes: vec<box<node>> } 

but can't derive clone because node doesn't implement , whenever try example kind of node in test so:

#[test] fn test_plain_string() {     let mut parser = parser::new("plain_string", "hello world");     parser.parse();     assert_eq!(1, parser.root.nodes.len());     let ref node = parser.root.nodes[0];     let kind = node.get_kind();     assert_eq!(kind, nodekind::text); } 

i borrowing , sizing errors example:

src/parser.rs:186:20: 186:24 error: cannot move out of borrowed content [e0507] src/parser.rs:186         let kind = node.get_kind();                                      ^~~~ src/parser.rs:186:20: 186:24 error: cannot move value of type nodes::node + 'static: size of nodes::node + 'static cannot statically determined [e0161] src/parser.rs:186         let kind = node.get_kind(); 

something similar test is in tests.

how supposed access trait objects or approach flawed in rust? possible implement traits trait (like debug) trait or have implement debug manually each struct embedding node?

the error comes fact get_kind method on node expects self value, rather &self. passing self value means method takes ownership of object (and therefore drops , end of method), not necessary here. in general, should use &self default, change &mut self if need mutate object, or self if need consume object (e.g. because need move 1 of object's fields elsewhere , don't want clone it).

by way, noticed implemented tostring structs. however, documentation tostring says:

this trait automatically implemented type implements display trait. such, tostring shouldn't implemented directly: display should implemented instead, , tostring implementation free.


instead of using trait, consider using enum, if types of nodes known in advance , don't need extensibility. also, if later on need determine type of node, it'll more natural enum (just pattern matching).

it appears need of node types have kind , position attribute. depending on how you're going use these nodes, might find more useful define struct these fields plus enum type-specific fields.

struct node {     //kind: nodekind, // redundant!     position: usize,     specific: specificnode, }  enum specificnode {     list(vec<box<node>>),     text(string),     variableblock(box<node>),     identifier(string),     int(i32),     float(f32),     bool(bool), } 

hmm, specificnode enum looks lot nodekind enum, doesn't it? in fact, kind field becomes redundant, because can determine kind looking @ variant of specific field.

now, instead of implementing methods separately on each type of node, define them once, though each method need pattern match self in order access data of variant.

if have methods apply 1 particular variant (e.g. method makes sense on list), enum approach, you'd able invoke on type of node, there no distinct types each enum variant (as of rust 1.6; there discussions introducing feature). however, code work on abstract node of time, , you'd have verify kind of node have before calling method anyway, might move logic directly methods.


Comments

Popular posts from this blog

sublimetext3 - what keyboard shortcut is to comment/uncomment for this script tag in sublime -

java - No use of nillable="0" in SOAP Webservice -

ubuntu - Laravel 5.2 quickstart guide gives Not Found Error -