What to do when I want to return a value from one arm of an if, and a reference from the other?

fn do_thing(strings: Vec<String>, key: usize) -> String {
  if let Some(my_string) = strings.get(key) {
     my_string
   } else {
     let other_string: String = ask_user();
     other_string
   }
}

I'm trying to figure out what the best way to write the above code is. Obviously at present it does not compile as get returns a Option<&str>. I can make it compile by switching get for remove, however this means mutating the vec, which makes sense from a borrowing perspective as the string returned needs to have a single owner, but in a functional programming-inspired language like Rust using mutation just to satisfy the borrow checker feels wrong to me. Are there other ways to solve issues like this? Or ways to avoid getting in to this situation in the first place? Or is mutation here considered idiomatic?

Rust might have some functional inspirations but it has no particular aversion to mutation. If anything the language quite likes mutation, as it's gone through a great deal of effort to make it safe. So if popping from the Vec fits your requirements, then by all means go for it. Though if you're going to be doing lots of random-access removals, you might be better served by a HashMap or something instead of a Vec

 _____________________________________
< Hello! Is it me you're looking for? >
 -------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
10 Likes

From the function as written you can't return a &str, since the function takes ownership of the Vec and the strings are freed when it returns. In this case (you don't need any of the other elements anymore) it's perfectly fine to take what you want (one String) and let the rest get dropped.

If you change the function to take a &[String] instead, you can return a &str, and then a Cow is the right solution.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.