2015-12-21 27 views
-1

我遇到了一些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 

回答

3

我假設你讀過其他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 s實施Deref<Target = str>,這意味着他們可以參與deref強制

比賽隊伍類型爲&str。當比較這兩種類型時,編譯器會看到你有一個&String並試圖將其與&str相匹配。它會自動解引用這兩個值並應用deref強制。然而,str不能是一個獨立的類型,因此你會得到錯誤。

使用&arg[..]代替觸發Index特徵。這會產生一個&str,因此匹配手段不會執行任何自動解引用或強制。

此外:

  1. 沒有必要爲一個明確的類型上output
  2. 使用的功能/關閉結束隱含的回報。
  3. 沒有必要致電to_string,因爲arg已經是String

爲了好玩,這裏是一個使用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 
} 
+0

感謝您的提示:) – Earlz

+2

我可能是錯誤的,但不是最好使用'&* x'過'&X [..]'現在? – Veedrac

+0

@Veedrac好點!我不確定*哪一種比較習慣。我認爲我在「1.0之前的日子」中選擇了'&x [..]',之後就沒有想太多了。兩者都應該編譯成相同的代碼,所以這是一個看起來更明顯的問題,我猜。 – Shepmaster