不幸的是,我在管理 Rust 中与字符串和结构相关的生命周期时遇到了很多麻烦。
#[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)的对象向量。
到目前为止,我已经尝试在内部 map
内或外部声明 date
,尝试使用 Arc
来管理 >date
变量,尝试使用和不使用 move
关键字的内部循环。
但是,我就是找不到一种方法来使这些 map
方法中的变量绑定(bind)持续适当的时间。任何帮助将不胜感激。
当前产生的错误是:
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.
元问题:这是 Rust 中 map
的适当使用,还是应该使用正常迭代?我之前也尝试过迭代,但也因内存检查而受阻。
最佳答案
如果要在结构中存储引用,那么这些引用必须引用拥有比该结构生命周期更长的所有者的对象。此外,&'static
引用必须引用在程序执行的整个持续时间内有效的对象。对于 date
和 song
字段来说,这两者都不成立。
这里,SongEntry
结构应该只拥有 date
和 song
对象。
struct SongEntry {
date: String,
song: Song,
}
对于date
字段,只需使用 to_string
将字符串切片 (&str
) 转换为拥有的字符串 (String
)方法。对于 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_contents
是一个对 SongEntry
对象的迭代器进行迭代的迭代器(外部迭代器对文件进行迭代,内部迭代器对文件中的条目进行迭代)。如果您希望直接拥有 SongEntry
对象的迭代器,请使用 flat_map
而不是路径
上的map
。然后您可以使用 collect
如有必要,在最终迭代器上将结果收集到向量中(如果您只想对结果进行一次迭代,请不要使用 collect
!)。
关于json - Rust 变量 'does not live long enough' 和 'conflicting requirements',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42464230/