2017-07-18 29 views
1

我试图将C中的旧编译器教科书中的翻译器/解析器示例移植到Rust中。在标准偏差处使用匹配偷看

我有以下代码:

use std::io::Read; 

fn lexan() { 
    let mut input = std::io::stdin().bytes().peekable(); 
    loop { 
     match input.peek() { 
      Some(&ch) => { 
       match ch { 
        _ => println!("{:?}", input.next()), 
       } 
      } 
      None => break, 
     } 
    } 
} 

在这一点上我没有积极尝试解析输入,只是让我围绕如何match工作头。目标是将解析分支添加到内部匹配中。可惜这不能编译,因为我似乎理解比赛的语义失败:

error[E0507]: cannot move out of borrowed content 
--> src/main.rs:7:18 
    | 
7 |    Some(&ch) => { 
    |     ^-- 
    |     || 
    |     |hint: to prevent move, use `ref ch` or `ref mut ch` 
    |     cannot move out of borrowed content 

据我了解,这个错误是因为我没有自己的match的返回值。事情是,我不相信我正在使用任一比赛的返回值。我想也许input.next()可能是问题所在,但是在使用或不使用此部分(或实际上,整个println!调用)时会发生相同的错误。

我在这里错过了什么?自从我看了Rust以来,一直有一段时间(并且从未付出过很大的努力),而且这种性质的大多数搜索结果似乎都过时了。

+0

您是否尝试过编译器提示的内容?有什么不足呢? – Shepmaster

+0

我没有,因为我不指望'ch'在这里应该被认为是可变的。然而,这种改变似乎将代码中的问题进一步转移。 – user3662805

+0

如果我是你,我会读取所有输入到内存中,然后遍历* * :) –

回答

1

它有没有关系的match返回值,甚至match本身::

use std::io::Read; 

fn lexan() { 
    let mut input = std::io::stdin().bytes().peekable(); 
    if let Some(&ch) = input.peek() {} 
} 

的问题是,你试图同时取消引用它到Peekable::peek结果结合(这就是&,&ch呢)。在这种情况下,返回类型是Option<&Result<u8, std::io::Error>>,因为Bytes迭代器从基础流返回错误。由于这种类型不实现Copy,试图取消引用类型要求您转移该值的所有权。你不能这样做,因为你不拥有原始值 - 因此是错误信息。

导致无法复制的部分是Result的错误类型。因此,您可以匹配更深的一个级别:

match input.peek() { 
    Some(&Ok(ch)) => { 
     match ch { 
      _ => println!("{:?}", input.next()), 
     } 
    } 
    Some(&Err(_)) => panic!(), 
    None => break, 
} 

请注意,此代码非常接近无法编译。当调用next时,peek的结果将失效,因此对该代码的很多小改动都会触发借用检查程序使代码失败。我实际上有点惊讶上面的工作第一次去。

如果你不关心错误可言,你可以做

while let Some(&Ok(ch)) = input.peek() { 
    match ch { 
     _ => println!("{:?}", input.next()), 
    } 
} 

不幸的是,你不能分割的中间,因为这将导致input借调用next期间持续:

while let Some(x) = input.peek() { 
    match *x { 
     Ok(ch) => { 
      match ch { 
       _ => println!("{:?}", input.next()), 
      } 
     } 
     Err(_) => {} 
    } 

    // Could still use `x` here, compiler doesn't currently see that we don't 
} 
+0

谢谢,我明白了'正在做什么,但是我没有想到在比赛中发生绑定(现在看起来很明显)。在你的最后一个提示中:为什么在这种情况下,如果在比赛区块中'peek'无效,那么这很重要吗?我把(匹配)看作(模糊地)在语义上类似于一个案例,没有经过。 input.next'被调用后,它的有效性不应该是不相关的吗? – user3662805

+0

@ user3662805我在最后一个示例中添加了一条评论。 TL; DR:这将需要*非词汇生存时间*,这是一个备受期待的功能,但不是我们现在拥有的功能之一。 – Shepmaster