今天我第一次尝试使用Rust(写一个XML标记器),自然不明白一切:
我有一个带字段的结构,可以采用枚举值:
enum State { Outside, InATag(~str) }
struct Tokenizer { state: State }
在impl Tokenizer
中,我希望匹配当前状态,并在某些情况下更改它,但这总是会出现use of moved value
错误。
H访问和/或声明状态字段,以便我可以匹配它并在匹配分支中更改其值?
很抱歉这个混乱,我打算更改Tokenizer的状态字段,而不是状态的String字段!
match self.state {
InATag(name) => self.state = Outside,
Outside => ()
}
答案 0 :(得分:4)
如果没有更具体的例子,很难说这是否能解决您的问题,但您可以在匹配模式中使用ref
来引用匹配的子结构,并且可以使用{{1使该引用变得可变。
所以,在你的例子中:
ref mut
或者如果您需要匹配Tokenizer状态的其他部分,这也适用:
enum State { Outside, InATag(~str) }
struct Tokenizer { state: State }
fn main() {
let mut t = Tokenizer { state: InATag(~"foo") };
match t.state {
InATag(ref mut _s) => { *_s = ~"bar"; }
Outside => { /* impossible */ }
}
io::println(fmt!("Hello World: %?", t));
}
请注意,在执行此类代码时,由于别名导致无意中遇到借用检查违规行为非常容易。例如,对于上面第二个示例,将不会编译,这是一个相对较小的更改:
fn main() {
let mut t = Tokenizer { state: InATag(~"foo") };
match t {
Tokenizer { state: InATag(ref mut _s) } => { *_s = ~"bar"; }
Tokenizer { state: Outside } => { /* impossible */ }
}
io::println(fmt!("Hello World: %?", t));
}
导致来自rustc的以下消息:
fn main() {
let mut t = Tokenizer { state: InATag(~"foo") };
match &t {
&Tokenizer { state: InATag(ref mut _s) } => { *_s = ~"bar"; }
&Tokenizer { state: Outside } => { /* impossible */ }
}
io::println(fmt!("Hello World: %?", t));
}
因为您还想要在/tmp/m.rs:7:35: 7:46 error: illegal borrow: creating mutable alias to enum content
/tmp/m.rs:7 &Tokenizer { state: InATag(ref mut _s) } => { *_s = ~"bar"; }
^~~~~~~~~~~
error: aborting due to previous error
&t
答案 1 :(得分:2)
好的,有了问题的澄清变体,这是我修改后的答案:
enum State { Outside, InATag(~str) }
struct Tokenizer { state: State }
impl Tokenizer {
fn toggle(&mut self) {
match self {
&Tokenizer { state: InATag(*) } => { self.state = Outside }
&Tokenizer { state: Outside } => { self.state = InATag(~"baz") }
}
}
}
fn main() {
let mut t1 = Tokenizer { state: InATag(~"foo") };
match t1 {
Tokenizer { state: InATag(*) } => { t1.state = Outside }
Tokenizer { state: Outside } => { /* impossible */ }
}
io::println(fmt!("Hello t1: %?", t1));
let mut t2 = Tokenizer { state: InATag(~"bar") };
t2.toggle();
io::println(fmt!("World t2: %?", t2));
}
我承认,我实际上并没有想到它会像上面那样简单,而且我很容易相信上述代码的微小变化可能导致它开始无法借用 - 检查。但如果没有来自提问者的更充实的例子,很难说上述代码是否适合他的目的。
哦,这是我编译并运行代码时的输出:
% rustc /tmp/m.rs
warning: no debug symbols in executable (-arch x86_64)
% /tmp/m
Hello t1: {state: Outside}
World t2: {state: Outside}
%