Как выражение соответствия интерпретирует значения и ссылки? - PullRequest
0 голосов
/ 29 июня 2018

В этом примере, почему я могу разыменовать t в выражении соответствия, но не в строке непосредственно выше?

fn tree_weight_v2(t: &BinaryTree) -> i32 {
    // let x = *t; // if uncommented, error: "Cannot move out of borrowed content"
    match *t {
        BinaryTree::Leaf(payload) => payload,
        BinaryTree::Node(ref left, payload, ref right) => {
            tree_weight_v2(left) + payload + tree_weight_v2(right)
        }
    }
}

#[test]
fn tree_demo_2() {
    let tree = sample_tree();
    assert_eq!(tree_weight_v2(&tree), (1 + 2 + 3) + 4 + 5);
    assert_eq!(tree_weight_v2(&tree), (1 + 2 + 3) + 4 + 5);
    // no error ^ meaning tree_weight_v2 is not taking ownership of tree
}

enum BinaryTree {
    Leaf(i32),
    Node(Box<BinaryTree>, i32, Box<BinaryTree>)
}

fn sample_tree() -> BinaryTree {
    let l1 = Box::new(BinaryTree::Leaf(1));
    let l3 = Box::new(BinaryTree::Leaf(3));
    let n2 = Box::new(BinaryTree::Node(l1, 2, l3));
    let l5 = Box::new(BinaryTree::Leaf(5));

    BinaryTree::Node(n2, 4, l5)
}

площадка

Я не верю, что то, что делает код помимо выражения match, важно, если, конечно, это не источник моей путаницы.

Мне также любопытно, как выражения соответствия обрабатывают разыменованные значения. В частности, поскольку выражение соответствия представляет собой значение типа BinaryTree (без каких-либо ссылок), почему выражение соответствия не пытается завладеть им? В более общем смысле, как Rust match интерпретирует разницу между разыменованным указателем на значение и нормальным значением?

1 Ответ

0 голосов
/ 30 июня 2018

let x = *t не работает, поскольку он перемещен из ссылки. То есть это означает, что при разыменовании t вы получите BinaryTree (без ссылки). BinaryTree заимствовано в функции, поэтому присвоение его с помощью let x = *t переместит его в x, что невозможно, так как оно заимствовано.

Совпадение работает, потому что match заимствует переменную. match *t не удалит его, но заимствует BinaryTree. Это особый синтаксис в Rust, и заимствование происходит за кулисами. Вы можете думать об этом:

fn tree_weight_v2(t: &BinaryTree) -> i32 {
    match &*t {
        &BinaryTree::Leaf(payload) => payload,
        &BinaryTree::Node(ref left, payload, ref right) => {
            tree_weight_v2(left) + payload + tree_weight_v2(right)
        }
    }
}

но все ссылки не нужны.


Смотри также:

...