json - Rust 变量 'does not live long enough' 和 'conflicting requirements'

标签 json rust

不幸的是,我在管理 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 引用必须引用在程序执行的整个持续时间内有效的对象。对于 datesong 字段来说,这两者都不成立。

这里,SongEntry 结构应该只拥有 datesong 对象。

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/

相关文章:

java - 如何使用Apache Avro序列化JSON文档,然后写入Cassandra?

javascript - 如何使用 javascript 将 json 对象的字段名称设置为对象数组中的值?

rust - [repr(C)] 是否传播给子成员?

rust - 如何同时获取对两个数组元素的可变引用?

compiler-errors - Rust 编译错误 : process didn't exit successfully

java - Jackson:在将对象序列化为 json 时自定义转义双引号

json - Typescript with TypeLite - 运行时类型检查

javascript - 如何插入json数组?

arrays - 将数组从 Julia 发送到 Rust(使用 "ccall")

rust - 为什么需要使用加号运算符 (Iterator<Item = &Foo> + 'a) 为特征添加生命周期?