查看什么是编译器错误消息:
error: cannot move out of borrowed content [E0507] Some(&op) => { ^~~ note: attempting to move value to here Some(&op) => { ^~ help: to prevent the move, use `ref op` or `ref mut op` to capture value by reference
尽管从技术上讲是正确的,但使用起来Some(ref op)
有点愚蠢,因为类型op
会是双引用(&&Op
)。相反,我们只需删除&
和即可Some(op)
。
这是一个困扰人们的常见错误,因为要正确使用它,您必须熟悉模式匹配和引用,再加上Rust严格的借位检查器。当你有的时候Some(&op)
,那说
匹配的
Option
是变体Some
。在Some
必须包含的值的参考。所指事物应从其所在位置移出并放入op
。
模式匹配时,这两个关键字ref
和mut
可以起作用。它们不是模式匹配的,而是它们控制如何将值绑定到变量名。它们是&
和的类似物mut
。
这导致我们进入下一个错误:
error: mismatched types: expected `&Op`, found `Op` Op::Not(input) => return eval_output(input.as_str(), outputs), ^~~~~~~~~~~~~~
match *some_reference
在可能的情况下最好这样做,但是在这种情况下您不能这样做。因此,我们需要更新模式以匹配对Op
— 的引用&Op
。看看接下来会发生什么错误...
error: cannot move out of borrowed content [E0507] &Op::Not(input) => return eval_output(input.as_str(), outputs), ^~~~~~~~~~~~~~~
是我们以前的朋友。这次,我们将遵循编译器的建议,并将其更改为ref input
。还有更多变化,我们有:
use std::collections::HashMap; enum Op { Not(String), Value(u16), } fn eval_output(output: &str, outputs: &HashMap) -> u16 { match outputs.get(output) { Some(op) => { match op { &Op::Not(ref input) => eval_output(input, outputs), &Op::Value(value) => value, } } None => panic!("Did not find input for wire {}", output), } } fn main() { let mut outputs = HashMap::new(); outputs.insert("x".into(), Op::Value(17)); outputs.insert("a".into(), Op::Not("x".into())); println!("Calculated output is {}", eval_output("a", &outputs)); }
不需要use std::prelude::*;
-编译器自动插入。
as_str
在稳定的Rust中不存在。对String
(&String
)的引用可以使用deref强制来充当字符串切片(&str
)。
我用into
代替,String::from
因为它有点短。没有更好的理由。