I am pressing on with learning Rust. I feel like the lifetime penny has half dropped for me, and I need a bit of help getting it the rest of the way.
I have come up with a silly little project to facilitate the learning process. It is a simulated economy, whereby economic agents trade with each other.
use std::collections::HashMap;
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
enum ResourceName {
Food
}
type AgentId = u32;
struct Offer {
maker_id:AgentId,
resource_name:ResourceName,
min_amount:f64,
max_amount:f64,
price:f64
}
struct ProposedTrade<'a> {
taker_id:AgentId,
offer:&'a Offer,
amount:f64,
value:f64
}
trait EconomicAgent {
fn set_offers(&self) -> Vec<Offer>;
fn proposed_trades<'a>(&self, offers:& 'a HashMap<ResourceName, Vec<&Offer>>) -> Vec<ProposedTrade<'a>>;
fn settle_maker_side<'a>(&mut self, propsed_trades:Vec<&'a ProposedTrade<'a>>) -> Vec<&ProposedTrade<'a>>;
fn settle_taker_side<'a>(&mut self, proposed_trades:Vec<&'a ProposedTrade>);
}
struct AgentCollection {
available_ids: Vec<AgentId>,
agents: HashMap<AgentId, Box<dyn EconomicAgent>>
}
impl AgentCollection {
fn create_agent(&mut self, f: fn(AgentId) -> Box<dyn EconomicAgent>) -> Option<AgentId> {
let id = self.available_ids.pop()?;
let agent = f(id);
self.agents.insert(id, agent);
Some(id)
}
fn destroy_agent(&mut self, agent_id: AgentId) {
self.agents.remove(&agent_id);
self.available_ids.push(agent_id);
}
}
fn economy_loop<'a>(mut agent_col:AgentCollection){
use itertools::Itertools;
let mut offers : Vec<Offer> =
agent_col.agents.iter()
.flat_map(|(_, agent)|agent.set_offers())
.collect();
offers.sort_by(|o1, o2|o1.price.partial_cmp(&o2.price).unwrap());
let offer_map =
offers.iter()
.map(|offer|(offer.resource_name, offer))
.into_group_map();
let mut proposed_trades : Vec<ProposedTrade> =
agent_col.agents.iter()
.flat_map(|(_, agent)|agent.proposed_trades(&offer_map))
.collect();
use rand::thread_rng;
use rand::seq::SliceRandom;
proposed_trades.shuffle(&mut thread_rng());
let proposed_trades_map =
proposed_trades.iter()
.map(|pt|(pt.offer.maker_id, pt))
.into_group_map();
let partially_settled:Vec<&ProposedTrade> =
proposed_trades_map.iter().flat_map(|(maker_id, pts)|{
let mut maker = agent_col.agents.get_mut(&maker_id).unwrap();
maker.settle_maker_side(*pts)
}).collect()
;
}
fn main() {
println!("Hello, world!");
}
The compiler does not like the last batch of code. Sorry for the long code snippet, I tried to distill the problem down to something minimal, but my minimal code did not present any problems, which further highlights my lack of understanding here.
Would be minimal code:
struct Foo(usize);
struct Bar{
foo_count:usize
}
impl Bar {
fn choose_foos<'a>(&mut self, foos:Vec<&'a Foo>) -> Vec<&'a Foo> {
self.foo_count = foos.len();
foos.into_iter().filter(|foo|foo.0 > 5).collect()
}
}
fn foo_bar(bar_map:HashMap<usize, Bar>, bar_id:usize, foos:Vec<&Foo>) -> Vec<&Foo>{
let mut bar = bar_map.get_mut(&bar_id).unwrap();
bar.choose_foos(foos)
}