2017-02-26 1 views
1

불행히도 문자열과 구조체와 관련하여 녹의 수명을 관리하는 데 많은 어려움을 겪고 있습니다.녹 변수가 '충분히 길지 않습니다'및 '충돌 요구 사항'

#[macro_use] 
extern crate serde_derive; 
extern crate serde_json; 
use serde_json::Value; 
use std::fs::File; 
use std::path::Path; 
use std::io::prelude::*; 
use std::fs; 
use std::cell::RefCell; 

#[derive(Serialize, Deserialize, Debug)] 
struct Song { 
    artist: String, 
} 

struct SongEntry { 
    date: &'static str, 
    song: &'static Song, 
} 

fn main() { 
    let paths = fs::read_dir("./charts/").unwrap(); 

    let fileContents = paths.map(| path | { 
     let p = path.unwrap().path(); 
     let file = File::open(&p).unwrap(); 
     let v: Vec<Song> = serde_json::from_reader(file).unwrap(); 
     return v.iter().map(move | song | { 
      let date = p.file_stem().unwrap().to_str().unwrap(); 
      return SongEntry { 
       song: song, 
       date: date, 
      }; 
     }) 
    }); 
} 

여기 메모리를 관리 많은 변화를 시도,하지만 서로에 대한 하나의 오류를 교환하는 것했습니다.

디렉토리의 JSON 파일을 반복 실행하고 구문 분석 한 다음 날짜 (파일 이름의)와 내용 (파싱 된 JSON의)을 포함하는 객체 벡터를 조합합니다.

는 지금까지 내가 내부 mapdate를 선언하려고했습니다, 또는 그것의 외부에서 date 변수를 관리 할 수 ​​Arc를 사용하여 시도로하고 move 키워드없이 내부 루프를 시도했다.

그러나 이러한 올바른 변수 시간 동안 이러한 map 메서드의 변수 바인딩을 가져 오는 방법을 찾을 수 없습니다. 어떤 도움이라도 대단히 감사 할 것입니다. 이 녹 map의 적절한 사용, 또는 내가 대신 정상 반복을 사용한다 :

Compiling kanye v0.1.0 (file:///Users/tmcw/src/sandbox/kanye) 
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements 
    --> src/main.rs:29:26 
    | 
29 |    let date = p.file_stem().unwrap().to_str().unwrap(); 
    |       ^^^^^^^^^ 
    | 
note: first, the lifetime cannot outlive the lifetime as defined on the body at 28:42... 
    --> src/main.rs:28:43 
    | 
28 |   return v.iter().map(move | song | { 
    | ___________________________________________^ starting here... 
29 | |    let date = p.file_stem().unwrap().to_str().unwrap(); 
30 | |    return SongEntry { 
31 | |     song: song, 
32 | |     date: date, 
33 | |    }; 
34 | |   }) 
    | |_________^ ...ending here 
note: ...so that closure can access `p` 
    --> src/main.rs:29:24 
    | 
29 |    let date = p.file_stem().unwrap().to_str().unwrap(); 
    |      ^
    = note: but, the lifetime must be valid for the static lifetime... 
note: ...so that reference does not outlive borrowed content 
    --> src/main.rs:32:23 
    | 
32 |     date: date, 
    |      ^^^^ 

error: aborting due to previous error 

error: Could not compile `kanye`. 

To learn more, run the command again with --verbose. 

메타 - 질문 :

생산 된 현재 오류

은? 나는 또한 전에 반복을 시도했지만 또한 메모리 검사에 의해 방해 받았다.

답변

2

참조를 구조체에 저장하려는 경우 해당 참조는 해당 구조체보다 오래 사는 소유자가있는 객체를 참조해야합니다. 또한 &'static 참조는 프로그램 실행의 전체 기간 동안 유효한 개체를 참조해야합니다. datesong 필드에 대해서도 마찬가지입니다.

구조체 SongEntry 구조체는 단순히 datesong 개체를 소유해야합니다.

struct SongEntry { 
    date: String, 
    song: Song, 
} 

date 필드의 경우 단순히 to_string 방법으로 소유 된 문자열 (String)로 문자열 조각 (&str)를 변환합니다. song 필드의 경우 벡터 v에서 소유권을 이동해야합니다. 그러나 Vec::iter은 해당 항목에 대한 차용 된 참조 만 산출합니다. 대신 Vec::into_iter을 사용해야하며,이 값은 프로세스에서 벡터를 소비하면서 직접 값을 반환합니다. 이때

fn main() { 
    let paths = fs::read_dir("./charts/").unwrap(); 

    let file_contents = paths.map(|path| { 
     let p = path.unwrap().path(); 
     let file = File::open(&p).unwrap(); 
     let v: Vec<Song> = serde_json::from_reader(file).unwrap(); 
     v.into_iter().map(move |song| { 
      let date = p.file_stem().unwrap().to_str().unwrap().to_string(); 
      SongEntry { 
       date: date, 
       song: song, 
      } 
     }) 
    }); 
} 

, file_contentsSongEntry 개체 반복자 반복자 (파일보다 외측 반복자 반복하는 파일의 항목 위에 내부 반복자 반복)이다. SongEntry 객체의 반복자를 직접 갖고 싶다면 map 대신 flat_mappaths에 사용하십시오. 그런 다음 최종 반복기에서 collect을 사용하여 결과를 벡터로 수집 할 수 있습니다 (결과를 한 번만 반복 할 경우 collect을 사용하지 마십시오).

+0

우수하고 철저한 답변에 감사드립니다. 너무 많이 설명합니다. – tmcw