当匹配字符串文字时,“类型str没有实现大小”吗?

时间:2015-12-21 20:05:41

标签: iterator rust match

我遇到一些Rust代码有问题。我有一个相当简单的函数,但它会在代码中抛出错误,似乎是无关的:

use std::env::Args;
fn without_xxx(args: Args) -> Vec<String>{
    let mut out: Vec<String> = vec![];
    let mut xxx = false;
    for arg in args{
        match &arg{
             "-" => xxx=true, //this line
            _ => out.push(arg.to_string())
        }
    }
    return out;
}

如果您注释掉标记的行,则不会显示错误。但是,通过这条简单的线条,它揭示了这组神秘的错误:

<anon>:7:9: 12:10 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
<anon>: 7         for arg in args{
<anon>: 8             match &arg{
<anon>: 9                 "-" => xxx=true,
<anon>:10                 _ => out.push(arg.to_string())
<anon>:11             }
<anon>:12         }
<anon>:7:9: 12:10 help: see the detailed explanation for E0277
<anon>:7:9: 12:10 note: `str` does not have a constant size known at compile-time
<anon>:7:9: 12:10 note: required by `core::option::Option::Some`
<anon>:7:13: 7:16 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
<anon>:7         for arg in args{
                     ^~~
<anon>:7:13: 7:16 help: see the detailed explanation for E0277
<anon>:7:13: 7:16 note: `str` does not have a constant size known at compile-time
<anon>:7:13: 7:16 note: all local variables must have a statically known size
<anon>:7:9: 12:10 error: type mismatch resolving `<std::env::Args as core::iter::Iterator>::Item == str`:
 expected struct `collections::string::String`,
    found str [E0271]
<anon>: 7         for arg in args{
<anon>: 8             match &arg{
<anon>: 9                 "-" => xxx=true,
<anon>:10                 _ => out.push(arg.to_string())
<anon>:11             }
<anon>:12         }
<anon>:7:9: 12:10 help: see the detailed explanation for E0271

1 个答案:

答案 0 :(得分:5)

我认为你已经阅读了有关questions的其他error,所以我只是介绍这个具体案例。

您想使用&arg[..]代替&arg

fn without_xxx(args: Args) -> Vec<String> {
    let mut out = vec![];
    let mut xxx = false;

    for arg in args {
        match &arg[..] {
             "-" => xxx = true,
            _ => out.push(arg)
        }
    }

    out
}

我承认错误是一个奇怪的错误。以下是我的想法:

当您执行&arg时,您正在引用StringString实施Deref<Target = str>,这意味着他们可以参与 deref强制

匹配组的类型为&str。比较这两种类型时,编译器会看到您有&String并尝试将其与&str匹配。它会自动取消引用这两个值并应用deref强制。但是,str不能是独立类型,因此您会收到错误。

使用&arg[..]会触发Index特征。这会产生&str,因此匹配臂不会进行任何自动解除引用或强制。

此外:

  1. output
  2. 上不需要显式类型
  3. 在函数/闭包结束时使用隐式返回。
  4. 由于to_string已经是arg,因此无需致电String
  5. 为了好玩,这是一个使用filter_mapcollect和普通if的版本:

    fn without_xxx(args: Args) -> Vec<String> {
        let mut xxx = false;
    
        let out = args.filter_map(|a| {
            if a == "-" {
                xxx = true;
                None
            } else {
                Some(a)
            }
        }).collect();
    
        // I assume you do something with `xxx` here
    
        out
    }
    

    可能具有性能优势,因为它可以潜在地分配向量大小的上限。

    另一个版本:

    fn without_xxx(args: Args) -> Vec<String> {
        let mut xxx = false;
    
        let out = args.filter(|a| {
            let matched = a == "-";
            xxx = xxx || matched;
            !matched
        }).collect();
    
        // I assume you do something with `xxx` here
    
        out
    }