Печать дерева - попытка доступа к полю, но поле с таким именем не найдено

Я пытаюсь написать свою первую программу на Rust. Я хочу напечатать простое дерево на экране, но не могу получить доступ к value собственность, это говорит

Ошибка 1 при попытке доступа к полю value по типу Node, но поле с таким именем не найдено 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 ответа

Решение

Просто потому что оба варианта Node иметь value поле, не означает, что вы можете получить к нему доступ напрямую. Вы можете получить его, сопоставив по значению (это эквивалентно):

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

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

Но если вы собираетесь делать это много, вы, вероятно, захотите добавить метод:

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

... который вы затем можете использовать так:

let value = leaf.get_value();

Поскольку все ваши варианты перечисления имеют одно и то же поле, вы можете извлечь поле во внешнюю структуру и сохранить только те поля, которые различаются внутри перечисления. Таким образом, у вас есть прямой доступ к внутреннему value поле. Когда вы хотите узнать, является ли ваш узел Branch или Leafнужно совпадать на kind поле. Также я предлагаю использовать Rc<Node> вместо *const Nodeкак доступ к значению *const Node указывает на необходимость небезопасного кода и, скорее всего, приведет к неприятностям в более сложном коде.

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) };
}

Я думаю, что вы действительно хотите, это следующий код: PlayPen

Используя мои магические способности интуиции, я предполагаю, что у вас есть такой код:

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

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

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

Который действительно имеет ошибку:

<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);
                            ^~~~~~~~~~

Проблема в том, что тип leaf является Node, а также Node имеет два варианта, Branch или же Leaf, Там нет типа с именем Node::Branch или же Node::Leaf, Вы должны соответствовать в перечислении, чтобы исчерпывающе обработать все случаи:

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),
    }
}
Другие вопросы по тегам