-1

Let's have a struct containing a vector of cities and a new_city function adding City to the vector. However, I got BorrowMutError which makes sense.

What should I do so I can call new_city multiple times (see below)? I would need to drop the borrow_mut reference in the new_city function but I don't know how.

//use std::rc::Rc;
use std::cell::RefCell;
use std::cell::Ref;

pub struct Simulation{
    cities: RefCell<Vec<City> >,
}


impl Simulation{

    pub fn new() -> Simulation
    {
        Simulation{
            cities: RefCell::new(Vec::new()),
        }
    }

    pub fn new_city(&self, name: &'static str) -> Ref<City> { 
        let city = City::new(name);
        self.cities.borrow_mut().push(city);

        Ref::map(self.cities.borrow(), |vec| vec.last().unwrap())
    }

}

#[derive(Debug, Copy, Clone)]
pub struct City {
    name: &'static str,
}

impl City{
    pub fn new(name: &'static str) -> City {
        City { name: name, }
    }
}

fn main(){

    let mut simulation = Simulation::new();

    let prg = simulation.new_city("Prague");
    let brn = simulation.new_city("Brno");
    let pls = simulation.new_city("Pilsen");


    println!("{:?}", prg);    

}

EDIT: Next use

Then I need prg and brn cities to add road between them with API (another vector in Simulation)

pub fn new_road(&self, from: &City, to: &City, time: i32) -> &Road {
         //Adding information about road to simulation
}

let d1 = simulation.new_road(&prg, &brn, 120);

Therefore I cannot drop prg or brn.

1 Answers1

0

You could simply introduce a new scope at the end of which the BorrowMut gets dropped:

pub fn new_city(&self, name: &'static str) -> Ref<City> {
    {
        let city = City::new(name);
        self.cities.borrow_mut().push(city);
    }
    Ref::map(self.cities.borrow(), |vec| vec.last().unwrap())
}

But you can't hold on to the Refs across new_city calls either.

fn main() {
    let mut simulation = Simulation::new();
    let prg = simulation.new_city("Prague");
    drop(prg);
    let brn = simulation.new_city("Brno");
}

You might want to wrap the cities in Rcs to be able to hold on to them across pushes:

pub struct Simulation{
    cities: RefCell<Vec<Rc<City>>>,
}
//...
impl Simulation {
    //...
    pub fn new_city(&self, name: &'static str) -> Rc<City> { 
        {
            let city = Rc::new(City::new(name));
            self.cities.borrow_mut().push(city);
        }

        self.cities.borrow().last().unwrap().clone()
    }
}
cafce25
  • 15,907
  • 4
  • 25
  • 31
  • This didn't help as the compiler still returns thread 'main' panicked at 'already borrowed: BorrowMutError'. But thanks. – Filip Čermák Dec 01 '22 at 14:29
  • @FilipČermák See the edit. `push`ing to a `Vec` might move all elements in it, thus you can't hold on to references across `push` calls. – cafce25 Dec 01 '22 at 14:29
  • Thanks, I have added the next part of the code (After EDIT: at the end) to see that I cannot drop prg or brn even when I should. I see I need to drop it but I still need to have a structure Simulation containing Cities and Roads. – Filip Čermák Dec 01 '22 at 14:41
  • @FilipČermák Edited once more, but it's now a duplicate of [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct) imo. – cafce25 Dec 01 '22 at 14:45