2

注意。この投稿はもともと、2 つの質問 (1 つのエラーが別の形で現れると私は信じていた) を含む大きな投稿の一部でしたが、サイトのガイドラインに準拠するために、2 つの個別の投稿に分割しました。最初の投稿はこちら.

次のようにレイアウトされた、1 行に 1 つの 3 単語のエントリを含む単純な構成テキスト ファイルを解析しようとしています。

ITEM name value
ITEM name value
//etc.

ここ(およびRustプレイグラウンド)で解析(およびその後のコンパイルエラー)を行う関数を再現しました:

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;
use std::collections::HashMap;

fn main() { }

pub fn parse(path: &Path) -> config_struct {

    let file = File::open(&path).unwrap();
    let reader = BufReader::new(&file);
    let line_iterator = reader.lines();
    let mut connection_map = HashMap::new();
    let mut target_map = HashMap::new();

    for line in line_iterator {

        let line_slice = line.unwrap();
        let word_vector: Vec<&str> = line_slice.split_whitespace().collect();

        if word_vector.len() != 3 { continue; }

        // no match statement   
        connection_map.insert(word_vector[1], word_vector[2]);
    }

    config_struct { connections: connection_map, targets: target_map }
}

pub struct config_struct<'a>  {
    // <name, value>
    connections: HashMap<&'a str, &'a str>,
    // <name, value>
    targets: HashMap<&'a str, &'a str>,
}
<anon>:20:38: 20:48 error: `line_slice` does not live long enough
<anon>:20         let word_vector: Vec<&str> = line_slice.split_whitespace().collect();
                                               ^~~~~~~~~~
note: in expansion of for loop expansion
<anon>:17:5: 26:6 note: expansion site
<anon>:9:44: 29:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 9:43...
<anon>:9 pub fn parse(path: &Path) -> config_struct {
<anon>:10 
<anon>:11     let file = File::open(&path).unwrap();
<anon>:12     let reader = BufReader::new(&file);
<anon>:13     let line_iterator = reader.lines();
<anon>:14     let mut connection_map = HashMap::new();
          ...
<anon>:19:40: 26:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 19:39
<anon>:19         let line_slice = line.unwrap();
<anon>:20         let word_vector: Vec<&str> = line_slice.split_whitespace().collect();
<anon>:21 
<anon>:22         if word_vector.len() != 3 { continue; }
<anon>:23 
<anon>:24         // no match statement   
          ...
error: aborting due to previous error

要するに、借用チェッカーに問題があります。私のコードでは、をword_vector指していない所有オブジェクトが取り込まれていませんline_sliceか? おそらくunwrap()またはcollect()参照を返し、範囲外になるのは参照であると考えましたが、アンラップ収集のRust Docsはそうではないと示唆しています。

4

1 に答える 1

3

&strは、それに含まれる値を格納するものなしでは存在できません。これは純粋に参照です (したがって) &

取得したファイルから読み取るStrings; これらはストレージを提供します。しかし、文字列のみを返そうとして、それらを削除しています。

また、次のように考えてください。

pub fn parse(path: &Path) -> config_struct<'???>;

戻り値の有効期間はどれくらいですか?

その部分について不平を言わなかった唯一の理由は、Path参照の有効期間と戻り値の有効期間が同じであると推測したためです。これは、 内の何かへの参照を返していることを意味しますPath

このような状況では、通常、Strings の代わりに&strs を格納する必要があります。&strそれぞれをStringwithに変換し.to_owned()ます。

于 2015-07-25T00:47:20.677 に答える