使用匹配偷看stdin

时间:2017-07-18 21:09:37

标签: parsing rust

我正在尝试将旧的编译器教科书中的翻译器/解析器示例从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的工作原理。目的是在内部匹配中添加解析分支。不幸的是,这无法编译,因为我似乎无法理解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之后已经有一段时间了(并且从未付出过那么大的努力),而且这种性质的搜索结果似乎已经过时了。

1 个答案:

答案 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,
}

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

如果您根本不关心错误,可以

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
}
相关问题