我对铁 rust 的终身保证越来越熟悉,我不确定我想要做的事情是否可能实现.
unwrap
时,在最后一次之前的线路上代码死机.编译器正确地理解persons_with_age
必须至少活到persons_and_zip_code_city_map.persons
岁;但我想向编译器发出信号,我希望它活到persons_and_zip_code_city_map
岁,因为它隐含地引用了persons_and_zip_code_city_map.zip_code_city_map
.也许我可以用一些零大小的类型来做这件事,或者以某种方式使用生命周期?
这将使此运行时错误变成编译时错误.
use std::collections::HashMap;
#[allow(dead_code)]
#[derive(Clone, Debug)]
struct Person {
name: String,
zip_code: u32,
useless_data: u16,
}
#[allow(dead_code)]
#[derive(Clone, Debug)]
struct PersonWithAge<'a> {
name: &'a str,
age: u16,
zip_code: &'a u32,
}
type ZipcodeCity = HashMap<u32, String>;
struct PersonsAndZipcodes {
pub persons: Vec<Person>,
pub zip_code_city_map: ZipcodeCity,
}
fn get_persons_with_zip_map(code: u32) -> PersonsAndZipcodes {
let persons = vec![
Person { name: "a".to_string(), zip_code: code, useless_data: 10 },
Person { name: "b".to_string(), zip_code: code, useless_data: 20 },
];
let mut zip_code_city_map = HashMap::new();
zip_code_city_map.insert(code, "street1".to_string());
return PersonsAndZipcodes {
persons,
zip_code_city_map,
}
}
fn get_persons_ages() -> Vec<u16> {
vec![30, 40]
}
fn main() {
// Here I get a vector of Persons (contains a zipcode) and a HashMap from a zipcode to a city.
// I make sure that every zipcode listed has an entry.
// While I could have added the city to the Person {}, this would use more memory,
// since N people can have the same zip_code, which would be added only once to the hashmap.
let mut persons_and_zip_code_city_map = get_persons_with_zip_map(1);
let persons = persons_and_zip_code_city_map.persons;
// Another API returns the ages of the persons
let ages = get_persons_ages();
assert!(persons.len() == ages.len());
// Here persons_with_age is created attaching the Age to a new object.
let mut persons_with_age = Vec::new();
for i in 0..ages.len() {
persons_with_age.push(
PersonWithAge {
name: &persons[i].name,
age: ages[i],
zip_code: &persons[i].zip_code,
}
);
}
println!("{:?}", persons_with_age);
// Here I get a reference to an specified person
let this_person = persons_with_age.get(0).unwrap();
// persons_and_zip_code_city_map is updated
persons_and_zip_code_city_map = get_persons_with_zip_map(2);
// Now I try to access the zipcode of `this_person` I have.
// My logic guarantees that `persons_and_zip_code_city_map.zip_code_city_map` would
// have this zipcode at the time I acquired `this_person`, but now it has been updated
// and the zipcode doesn't exist anymore.
// If I had assigned `persons.get(0).unwrap()` to `this_person`, the compiler catch this
// mistake, but it doesn't because I'm using `persons_with_age`.
// Is it possible to perhaps bind the lifetime of `persons_with_age` with `persons_and_zip_code_city_map`?
let this_person_city: String = persons_and_zip_code_city_map.zip_code_city_map.get(&this_person.zip_code).cloned().unwrap();
println!("{:?} {:?}", this_person, this_person_city);
}