Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 在对字段进行模式匹配时修改该字段_Pointers_Pattern Matching_Rust - Fatal编程技术网

Pointers 在对字段进行模式匹配时修改该字段

Pointers 在对字段进行模式匹配时修改该字段,pointers,pattern-matching,rust,Pointers,Pattern Matching,Rust,今天,我第一次尝试了Rust(编写XML标记器),但自然不了解所有内容: 我有一个带字段的结构,可以接受枚举值: enum State { Outside, InATag(~str) } struct Tokenizer { state: State } 在impl标记器中,我希望匹配当前状态,并在某些情况下对其进行更改,但是这总是会导致使用移动值错误 H访问和/或声明状态字段,以便在匹配分支中匹配并更改其值 很抱歉造成混淆,我的意思是更改标记器的状态字段,而不是状态的字符串字段 match

今天,我第一次尝试了Rust(编写XML标记器),但自然不了解所有内容:

我有一个带字段的结构,可以接受枚举值:

enum State { Outside, InATag(~str) }
struct Tokenizer { state: State }
impl标记器
中,我希望匹配当前状态,并在某些情况下对其进行更改,但是这总是会导致
使用移动值
错误

H访问和/或声明状态字段,以便在匹配分支中匹配并更改其值


很抱歉造成混淆,我的意思是更改标记器的状态字段,而不是状态的字符串字段

match self.state {
    InATag(name) => self.state = Outside,
    Outside => ()
}

如果没有更具体的示例,很难判断这是否能解决您的问题,但是您可以在匹配模式中使用
ref
来引用匹配的子结构,并且可以使用
ref mut
使该引用可变

因此,在您的示例中:

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的以下消息:

/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
的内部创建可变别名的同时,借用未完成的
&t
好的,下面是我的修订答案:

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}
% 

你使用的是什么版本的Rust?Rust语言变化很快,语法和语义还没有固定下来。特别是,我非常肯定,
match
的行为最近发生了变化(或者将发生变化,可能在0.7中)。这个答案当然有助于我理解更多关于生锈的内容,但我似乎表达得很糟糕:我想切换状态,而不是修改其值。抱歉搞混了!我会相应地更新我的问题。太棒了,谢谢!因此,在方法中需要一个指向self的可变指针,这很有意义!
% rustc /tmp/m.rs
warning: no debug symbols in executable (-arch x86_64)
% /tmp/m
Hello t1: {state: Outside}
World t2: {state: Outside}
%