我在Rust开发一个单词生成器 . 该应用程序包含两个主要结构: Letter
和 Alphabet
.
Letter
由单个字符和与其他字母关系的规则组成 .
Alphabet
包含元音和辅音的向量,以及带有对这些向量中字母的引用的散列映射 . 这样做是为了可以在O(1)时间内检索字母规则 .
我已经创建了一个工厂方法来从json字符串读取字母表(下面的代码),但我收到一个错误,说明字母表实例的活动时间不够长 .
src / word_generator / alphabet.rs:47:6:47:14错误:字母表的寿命不够src / word_generator / alphabet.rs:47 alphabet.add_letter(letter); src / word_generator / alphabet.rs:26:40:55:3注意:引用必须对26:39块上定义的匿名生命#1有效... src / word_generator / alphabet.rs:26 pub fn from_json (json:&str) - > Alphabet {注意:...但借用的值仅对于语句3后面的块后缀有效,在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很新,因此欢迎任何改进代码的建议 .
1 回答
这是一个较小的例子,可能是你开始的地方:
然后,您遵循编译器error1:
继续,直到你得到这样的东西:
根本问题是you cannot have references to your own members 2.在一般情况下,无论何时移动结构,所有成员变量的内存位置都会改变,使所有引用无效 . 这是件坏事,Rust会阻止你 .
您获得的错误消息指出's no possible lifetime that can satisfy what you want — the reference is only valid while the struct doesn't移动,但您想从方法返回结构,移动它 .
"But wait!"你说,“我有一个
Vec
,Vec
的内容在堆上,赢得't move!". While technically true (the best kind of true), Rust doesn'跟踪那个细粒度的东西 .这里的一般解决方案是将您的结构分成两部分 . 仅使用
Vec
将JSON中的所有内容解析为Alphabet
结构 . 然后将该结构(可能通过引用,可能通过值)传递给AlphabetSoup
结构 . 该结构可以同时创建HashMap
并提供缓存值的位置 .1较新的编译器实际上删除了这个建议,因为误报率太高而且引入了比它帮助更多的混乱 .
2实际上你可以引用自己的成员,但是你永远不能移动对象,这使得它在大多数情况下都不实用 .