1

I'm currently doing the advent of code exercises from 2021. Since I try to learn rust at the moment, I thought, I'll give it a go with it. I'm currently at day 12/1 and the objective is to find a way through a cave system. I modeled caves like so:

pub enum Cave {
    Big(String, Vec<Cave>),
    Small(String, Vec<Cave>, bool),
}

The String is the identifier of the cave, the Vec are all connected Caves, the bool in Cave::Small is due to the fact, that small caves can only be visited one time, so I have to keep track, if I already visited them. Now I want to read the file, which containes the data, create and connect the caves. For that I made a HashMap<&str, Cave>, in which I store all the caves, with the identifier as the key. For that, I wrote a function, that takes said HashMap and an &str, which is the identifier. The function looks into the HashMap to check, if it is already in it, and if not, create a new one and put it in the HashMap, which looks like this:

pub fn assure_cave(cave_system: &mut HashMap<&str, Cave>, name: &str) {
    if cave_system.contains_key(name) {
        if name
            .chars()
            .next()
            .expect("No name specified")
            .is_uppercase()
        {
            let cave = Cave::Big(name.to_string(), Vec::new());
            cave_system.insert(cave.name(), cave);
        } else {
            let cave = Cave::Small(name.to_string(), Vec::new(), false);
            cave_system.insert(cave.name(), cave);
        }
    };
}

cave.name() is just a small function, which returns a reference to the identifier. Now I get two errors in the line, where I try to insert into the HashMap. The first one is at cave.name(), it says "cave does not live long enough borrowed value does not live long enough". If I understand that correctly, this is due to the fact, that the local variable cave goes out of scope and name would reference nothing, which is not good. The second error is at cave and it says "cannot move out of cave because it is borrowed". I think, this is due to the name of the cave being borrowed, so I can't move cave into the map, since name would then point to nothing. Is this correct? How can I fix it? What I just tried and it seems to work is to change HashMap<&str, Cave> to HashMap<String, Cave> and insert with cave_system.insert(cave.name().to_string(), cave), but this seems pretty wasteful, since it copies a lot of strings unnecessarily. Is it possible to use a reference to the name as the key, and if so, how? And if not, is my workaround the right thing to do, or is there something more ideomatic?

Modi57
  • 205
  • 1
  • 10
  • Relevant: https://users.rust-lang.org/t/maps-objects-and-lifetimes/10670/8 – canton7 Feb 24 '22 at 13:23
  • Also relevant: https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct – Jmb Feb 24 '22 at 13:33
  • 2
    Do caves actually need to store their own name? Seems like a map from name → (adjacent, visited) would be sufficient. – BallpointBen Feb 24 '22 at 16:00

1 Answers1

1

After looking at the links from canton7 and Jmb, I decided to just leave it as is with the solution of making new string copies of the name.

Modi57
  • 205
  • 1
  • 10