59240


[言語処理100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100/#sec04)の4問目をRustで解いています。

[code]

    use std::collections::HashMap;
    
    pub fn problem04() {
        let s = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.";
        let sw: Vec<&str> = s.split(" ").collect();
    
        let mut map: HashMap<&str, usize> = HashMap::new();
        for i in 0..sw.len() {
            let word = sw[i].to_string();
            match i {
                1 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 19 => map.insert(&word[0..1], i),
                _ => map.insert(&word[0..2], i),
            };
        };
        println!("{:?}", map);
    }
    
[/code]

と書いて

[code]

    error[E0597]: `word` does not live long enough
      --> src/problem04.rs:12:30
       |
    12 |             _ => map.insert(&word[0..2], i),
       |                              ^^^^ borrowed value does not live long enough
    13 |         };
    14 |     };
       |     - `word` dropped here while still borrowed
    15 |     println!("{:?}", map);
       |                      --- borrow later used here
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0597`.
    error: Could not compile `nlp100`.
    
    To learn more, run the command again with --verbose.
    
    shell returned 101
    
[/code]

とエラーが出ました。

所有権周りで躓いていると思うのですが、どなたか解決策をご教示いただけないでしょうか。

よろしくおねがいします。


CC BY-SA 4.0
2019-09-24T04:50:07.917
59234
2019-09-24T08:13:28.670
34283
question
rust
Rustの所有権周りについて


このエラー内容は、変数`word`がループの各イテレーションの中だけでしか有効ではなく、頭2文字のスライスをHashMapに格納するのに必要な期間より短いというライフタイム周りのエラーです。

解決策としては、`sw[i].to_string()`
で新たにString型の値を生成していますが、これは必要がないので、元のString型の変数`s`の一部を指しているスライスである`sw[i]`からさらに切り出せば良いです。  
そうすると、切り取った部分を格納するHashMapよりも参照先となる変数`s`のほうが長く生存しているため、ライフタイムの制約を満たします。  
また、コンパイルは通りますが、HashMapは要素の順序が実行ごとに変わるため、そのまま結果とする場合にはBTreeMapを使うほうが好ましいです。

修正例：

[code]

    use std::collections::BTreeMap;
    
    pub fn main() {
        let s = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.";
        let sw: Vec<&str> = s.split(" ").collect();
    
        let mut map: BTreeMap<&str, usize> = BTreeMap::new();
        for i in 0..sw.len() {
            let word = sw[i];
            match i {
                1 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 19 => map.insert(&word[0..1], i),
                _ => map.insert(&word[0..2], i),
            };
        };
        println!("{:?}", map);
    }
    
[/code]


CC BY-SA 4.0
2019-09-24T08:13:28.670
59240
2019-09-24T08:13:28.670
7748
59234
answer