gpt4 book ai didi

rust - 工厂方法 : instance does not live long enough

转载 作者:行者123 更新时间:2023-11-29 08:05:33 24 4
gpt4 key购买 nike

我正在用 Rust 开发一个单词生成器。该应用程序由两个主要结构组成:LetterAlphabet

Letter 由单个字符和有关其与其他字母关系的规则组成。

Alphabet 包含元音和辅音的向量以及引用这些向量中的字母的 HashMap 。这样做是为了在 O(1) 时间内检索字母的规则。

我已经创建了一个工厂方法来从 json 字符串(下面的代码)中读取字母表,但是我收到一个错误,指出字母表实例的生命周期不够长。

src/word_generator/alphabet.rs:47:6: 47:14 error: alphabet does not live long enough src/word_generator/alphabet.rs:47 alphabet.add_letter(letter);

src/word_generator/alphabet.rs:26:40: 55:3 note: reference must be valid for the anonymous lifetime #1 defined on the block at 26:39... src/word_generator/alphabet.rs:26 pub fn from_json(json: &str)->Alphabet{

note: ...but borrowed value is only valid for the block suffix following statement 3 at 40:37 src/word_generator/alphabet.rs:40 let mut alphabet = Alphabet::new(); src/word_generator/alphabet.rs:41

我理解这个错误(我希望如此)但我不明白为什么会这样。为什么函数 new() 返回的 Alphabet 的实例被变量 alphabet 借用了?这不是移动操作吗?

pub struct Alphabet<'a>{
pub vowels: Vec<Letter>,
pub consonants: Vec<Letter>,
letters: HashMap<char,&'a Letter>
}

impl<'a> Alphabet<'a>{

pub fn new()->Alphabet<'a>{

return Alphabet{
vowels: Vec::new(),
consonants: Vec::new(),
letters: HashMap::new()
}

}

pub fn from_json(json: &str)->Alphabet{

let data :Json = match Json::from_str(json){
Ok(_data)=>_data,
Err(_err)=>panic!("Invalid JSON provided")
};

let letters = match data.as_array(){
Some(_letters)=>_letters,
None=>panic!("Expected JSON\'s root to be an array but found a different structure.")
};

let mut it = letters.iter();

let mut alphabet = Alphabet::new();

loop {
match it.next(){
Some(x) =>{

let letter : Letter= json::decode(&(x.to_string())).unwrap();
alphabet.add_letter(letter);

},
None => break,
}
}

return alphabet
}

fn add_letter(&'a mut self,ref l: Letter){

match l.letter_type {
LetterType::Vowel =>{
self.vowels.push(l.clone());
self.letters.insert(l.value, &self.vowels.last().unwrap());
},
LetterType::Consonant =>{
self.consonants.push(l.clone());
self.letters.insert(l.value, &self.consonants.last().unwrap());
}
}

}
}

P.S.:我是 Rust 的新手,所以非常欢迎任何改进代码的建议。

最佳答案

这是一个可能是您开始的小示例:

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() {}

然后您遵循了编译器错误1:

<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() {}

根本问题是you cannot have references to your own members 2。在一般情况下,无论何时移动结构,所有成员变量的内存位置都会改变,从而使所有引用无效。这是一件坏事,Rust 会阻止你。

您收到的错误消息表明没有可能的生命周期可以满足您的需求——引用仅在结构不移动时有效,但您希望从方法返回结构,移动它

“但是等等!”你说,“我有一个 Vec 并且 Vec 的内容在堆上,不会移动!”。虽然在技术上是真实的(最好的真实),但 Rust 不会在那么细粒度的级别上跟踪事物。

这里的一般解决方案是将您的结构分成两部分。将 JSON 中的所有内容解析为仅包含 VecAlphabet 结构。然后将该结构(可能通过引用,也可能通过值)传递给 AlphabetSoup 结构。该结构可以一次性创建 HashMap 并提供一个位置来缓存您的值。

1 较新的编译器实际上删除了这个建议,因为误报率太高,它带来的困惑多于帮助。

2 您实际上可以引用您自己的成员,但您永远不能移动该对象,这对大多数人来说是不切实际的例。

关于rust - 工厂方法 : instance does not live long enough,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30007087/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com