2016-12-19 5 views
2

私はクレートを使用して、単語のベクトルを枝打ちさせようとしています。それは簡単であるべき、しかしボローチェッカーは、私のコードを拒否し続けている:2つの変更可能な借用は同じ行で行われますか?

// Read user input 
let input = stdin(); 
let mut stemmer = Stemmer::new("english").unwrap(); 
for line in input.lock().lines() { 
    let line = line.unwrap(); 
    let mut query: Vec<_> = line.split_whitespace().collect(); 
    for t in &mut query { 
     *t = stemmer.stem_str(t); 
    } 
    // … 
} 

ボローチェッカーは、私はライン*t = stemmer.stem_str(t);stemmerの2つの可変借りを持っており、私のコードを拒否言います。 (ライン80はfor line in input.lock().lines()終わりのところのブロックである。)

57 18 error E0499 cannot borrow `stemmer` as mutable more than once at a time (first mutable borrow occurs here) (rust-cargo) 
57 18 error E0499 cannot borrow `stemmer` as mutable more than once at a time (second mutable borrow occurs here) (rust-cargo) 
80 5 info  E0499 first borrow ends here (rust-cargo) 

私が直接stem()メソッドを呼び出すと、私はStringを取得するが、その後、私はちょうどas_str()を呼び出して、バックに得られ&strを割り当てることを期待することはできません*t、借用チェッカーは「借りた金額が十分に長く生きていない」と不平を言うからです。

57 18 error   borrowed value does not live long enough (temporary value created here) (rust-cargo) 
57 18 info   consider using a `let` binding to increase its lifetime (rust-cargo) 
57 42 info   temporary value only lives until here (rust-cargo) 
80 5 info   temporary value needs to live until here (rust-cargo) 

これは、このライブラリの実装の詳細とは何かを持っている場合、私はわからないんだけど、私は本当にここで立ち往生感じています。私は、入力のベクトルを形づくることはとても難しいとは決して考えなかった。 documentation of stem_strから

+2

'or_exit(上記のコメントで言うように)' '以来、マクロではないようです! 'がありません(タイプミス?)。また、完全なコンパイラエラーを追加できますか? :) –

+0

@ LukasKalbertodtこれは、標準ライブラリではなく、コードベースで定義されたものです。おそらくコードサンプルを単に 'unwrap()'に変更するべきです。私は完全なエラーを含めました。 –

答えて

4

が返すstrの参照を使用すると、幹細胞または再stem_str呼び出さない限りのみ有効です。したがって、Rustのborrowcheckerは、あなたがそのような参照をスコープ内に持っていれば、そのうちの1つを機能させることはできません。

おそらく、これはステマー実装に実際に何らかの種類の内部バッファがあり、そのワードがそのままステートメントされて格納されるためです。

これは、文字列への参照を保持しながらstem_strを2回呼び出すことができないためです。そうするとは最初の文字列!を無効にします。

私はちょうどas_str()を呼び出すと、コンパイラが再び絶対的に正しいある*t

に戻って取得した&strを割り当てることを期待することはできません。値を作成しようとしているときに参照を取得し、参照を保存してから値を削除します。これはメモリの脆弱性であり、実行できません。

代わりに、String秒のベクトルを収集:

for line in input.lock().lines() { 
    let line = line.unwrap(); 
    let mut query: Vec<_> = line.split_whitespace() 
     .map(|t| stemmer.stem(t)) 
     .collect(); 
} 

は、私は非常にThe Rust Programming Languageを読み、参照がどのように機能するかを理解し、彼らが防ぐことをお勧めしたいです。これはの前にの間で、の所有権を持つ複雑なものになっています。これらの特別章:

+0

私は本を読んだことがありますが、明らかにそれらの概念はまだ消化に時間がかかります。あなたのメソッドで 'String'のベクトルを得ることができましたが、' Vec <&str> 'を期待する関数がいくつかあります。 'Vec 'を 'Vec <&str>'に変換する便利な方法はありますか? 'Vec <&str>'が必要な関数を書かず、その入力タイプを 'Vec 'に変更するのはより慣用的でしょうか? –

+0

@ JIXiang私はまた質問をSOで検索することを提案したい:[Vec をVec <&str>に変換する](http://stackoverflow.com/q/33216514/155423)。便利な場合は、 '&str'または' String'を受け入れるように関数の型を変更することができます。 – Shepmaster

+0

私はそれを最初に見つけましたが、私はVecの代わりに "Vector"を書くという間違いをしたようで、Googleからの関連する結果はありませんでした。この質問を出してくれてありがとう。 –

関連する問題