Printing a tree — attempted access of field, but no field with that name was found

602 Views Asked by At

I'm am trying to write my first Rust program. I want to print a simple tree on the screen, but I cannot access a value property, it says

Error 1 attempted access of field value on type Node, but no field with that name was found c:\users\zhukovskiy\documents\visual studio 2013\Projects\rust_application1\rust_application1\src\main.rs 21 20 rust_application1

use std::io;

enum Node {
    Branch { value: i32, next: *const Node },
    Leaf { value: i32 }
}

fn main() {
    let leaf = Node::Leaf { value: 15 };
    let branch = Node::Branch { value: 10, next: &leaf };
    let root = Node::Branch { value: 50, next: &branch };

    let current = root;
    loop {
        match current {
            Node::Branch => { println!("{}", current.value); current = current.next; },
            Node::Leaf => { println!("{}", current.value); break; }, 
        }
    }
}
3

There are 3 best solutions below

0
DK. On BEST ANSWER

Just because both variants of Node have a value field, doesn't mean you can access it directly. You can get it by matching on the value (these are equivalent):

let value = match leaf {
    Node::Branch { value, .. } => value,
    Node::Leaf { value } => value,
};

let value = match leaf {
    Node::Branch { value, .. } | Node::Leaf { value } => value,
};

But if you're going to do this a lot, you probably want to add a method:

impl Node {
    pub fn get_value(&self) -> i32 {
        match self {
            &Node::Branch { value, .. } => value,
            &Node::Leaf { value } => value,
        }
    }
}

...which you can then use like so:

let value = leaf.get_value();
0
Shepmaster On

Using my magic powers of intuition, I'm guessing you have some code like this:

enum Node {
    Branch { value: i32 },
    Leaf { value: i32 },
}

fn main() {
    let leaf = Node::Leaf { value: 15 };

    println!("{}", leaf.value);
}

Which indeed has the error:

<anon>:9:20: 9:30 error: attempted access of field `value` on type `Node`, but no field with that name was found
<anon>:9     println!("{}", leaf.value);
                            ^~~~~~~~~~

The problem is that the type of leaf is Node, and Node has two variants, Branch or Leaf. There is no type called Node::Branch or Node::Leaf. You need to match on the enumeration to exhaustively handle all the cases:

enum Node {
    Branch { value: i32 },
    Leaf { value: i32 },
}

fn main() {
    let leaf = Node::Leaf { value: 15 };

    match leaf {
        Node::Branch { value } => println!("Branch [{}]", value),
        Node::Leaf { value }   => println!("Leaf [{}]", value),
    }
}
0
oli_obk On

Since all your enum variants have the same field, you can extract the field into an outer struct and only keep the fields that differ inside the enum. This way you have direct access to the inner value field. When you want to find out whether your node is a Branch or a Leaf, you need to match on the kind field. Also I suggest to use an Rc<Node> instead of a *const Node, as accessing the value the *const Node points to requires unsafe code and will most likely get you into trouble in more complex code.

enum NodeKind {
    Branch(*const Node),
    Leaf,
}

use NodeKind::*;

struct Node {
    value: i32,
    kind: NodeKind,
}

fn main() {
    let leaf = Node{ value: 15, kind: Leaf };
    let branch = Node { value: 10, kind: Branch(&leaf) };
    let root = Node { value: 50, kind: Branch(&branch) };
}

I think what you actually want is the following code: PlayPen