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

Ear*_*rlz 0 iterator match rust

我遇到一些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;
}
Run Code Online (Sandbox Code Playgroud)

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

<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
Run Code Online (Sandbox Code Playgroud)

She*_*ter 5

我假设您已经阅读了有关错误的其他问题,因此我将仅介绍此具体案例.

你想用&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
}
Run Code Online (Sandbox Code Playgroud)

我承认错误很奇怪.这就是我的想法:

当你这样做时&arg,你正在参考a String.String实施Deref<Target = str>,这意味着他们可以参与deref胁迫.

匹配臂是类型&str.比较这两种类型时,编译器会看到你有一个&String并且正在尝试将它与a匹配&str.它会自动取消引用这两个值并应用deref强制.但是,a str不能是独立类型,因此您会收到错误.

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

另外:

  1. 不需要显式类型 output
  2. 在函数/闭包的末尾使用隐式返回.
  3. 没有必要打电话,to_string因为arg已经是String.

为了好玩,这是一个使用一个版本filter_map,collect和只是一个普通的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
}
Run Code Online (Sandbox Code Playgroud)

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

另一个版本:

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
}
Run Code Online (Sandbox Code Playgroud)

  • 我可能会弄错,但现在不宜在`&x [..]`上使用`&*x`? (2认同)