Reputation: 1363
I'm working on some coding challenges to learn Rust. In JavaScript it's pretty straightforward but in Rust I've had issues.
Here's what the JS would look like:
// Decode the message by reversing the words
function reverseWords(message) {
return message.join("").split(" ").reverse().join(" ").split("");
}
This is how far I could get in Rust solving the same problem:
// Decode the message by reversing the words
fn reverse_words(message: Vec<&str>) -> Vec<&str> {
let temp_a = message.join("");
let mut words: Vec<&str> = temp_a.split(" ").collect();
words.reverse();
let new_temp = words.join(" ");
let result = new_temp.split("").collect();
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn two_words() {
let input = "thief cake".split("").collect();
let actual = reverse_words(input).join("");
let expected = "cake thief";
assert_eq!(actual, expected);
}
}
This results in the following error:
error[E0515]: cannot return value referencing local variable `new_temp`
--> src/reverse_words/mod.rs:13:5
|
11 | let result = new_temp.split("").collect();
| ------------------ `new_temp` is borrowed here
12 |
13 | result
| ^^^^^^ returns a value referencing data owned by the current function
For more information about this error, try `rustc --explain E0515`.
I've tried all sorts of solutions to get around this ownership problem but there's clearly something I'm not understanding.
Here's a link to the playground if it helps: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d75a3894112c188780b9805661510c46
Upvotes: 1
Views: 1389
Reputation: 1212
Your issue is that let new_temp = words.join(" ")
is implicitly allocating memory for a String
and assigning it to new_temp
. The memory will be freed when the function returns as new_temp
goes out of scope at that point, yet your return value is a vector of pointers into that string.
If you inspect the variables through your code, it's generally pretty confused. message
in reverse_words(message: Vec<&str>)
is actually coming in as a vector of single characters, not words. Then words
is a collection of words, then that's being reversed and joining into a string, then finally the return value is a vector of string pointers.
I would suggest simplifying your type usage, at least initially. Start with a function definition as something simple like reverse_words(msg : String) -> String
and code logic in the function that solves that case.
If you specifically want to stay with Vec<&str>
, then probably easiest is to mutate the input in place, e.g. something like fn reverse_words(mut message: &Vec<&str>)
.
If you want to make your specific example work, the easiest way is just to return the String
that was created as follows:
// Decode the message by reversing the words
fn reverse_words(message: Vec<&str>) -> String {
let temp_a = message.join("");
let mut words: Vec<&str> = temp_a.split(" ").collect();
words.reverse();
words.join(" ")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn two_words() {
let input = "thief cake".split("").collect();
let actual = reverse_words(input);
let expected = "cake thief";
assert_eq!(actual, expected);
}
}
Upvotes: 2