这是一个可能是您开始的较小示例:
use std::collections::HashMap;
struct Letter;
struct Alphabet<'a>{
vowels: Vec<Letter>,
letters: HashMap<u8, &'a Letter>
}
impl<'a> Alphabet<'a> {
fn add(&mut self, l: Letter) {
self.vowels.push(l);
self.letters.insert(42, &self.vowels.last().unwrap());
}
}
fn main() {}
You then followed the compiler error1:
<anon>:12:46: 12:52 error: cannot infer an appropriate lifetime for lifetime parameter 'a in function call due to conflicting requirements
<anon>:12 self.letters.insert(42, &self.vowels.last().unwrap());
^~~~~~
<anon>:10:5: 13:6 help: consider using an explicit lifetime parameter as shown: fn add(&'a mut self, l: Letter)
继续,直到你得到这样的东西:
use std::collections::HashMap;
struct Letter;
struct Alphabet<'a>{
vowels: Vec<Letter>,
letters: HashMap<u8, &'a Letter>
}
impl<'a> Alphabet<'a> {
fn new() -> Alphabet<'a> {
Alphabet { vowels: Vec::new(), letters: HashMap::new() }
}
fn add(&'a mut self, l: Letter) {
self.vowels.push(l);
self.letters.insert(42, &self.vowels.last().unwrap());
}
fn parse() -> Alphabet<'a> {
let mut a = Alphabet::new();
a.add(Letter);
a
}
}
fn main() {}
The root problem is that you cannot have references to your own members 2. In the general case, whenever you moved the structure, then the memory location of all the member variables would change, invalidating all the references. This is a bad thing, and Rust would stop you.
您收到的错误消息指出,没有可能的生命周期可以满足您的需求 - 引用仅在结构不移动时有效,但您希望从方法返回结构,移动它.
“可是等等!”你说:“我有一个Vec
和内容Vec
在堆上并且不会移动!”。虽然从技术上来说是正确的(最好的正确方式),但 Rust 并没有在那么细粒度的级别上跟踪事物。
这里的一般解决方案是将您的结构分成两部分。将 JSON 中的所有内容解析为Alphabet
结构体仅包含Vec
s。然后将该结构(可能通过引用,也可能通过值)传递给AlphabetSoup
结构。该结构可以创建HashMap
一次全部完成并提供一个地方来缓存您的值。
1 Newer compilers actually removed this suggestion because the false-positive rate was too high and it introduced more confusion than it helped.
2 You actually can have references to your own members, but you can then never move the object, which makes it impractical for most cases.