When you concatenate rows, you need to allocate memory to store the result. The easiest way to start is with String and &str :
fn main() { let mut owned_string: String = "hello ".to_owned(); let borrowed_string: &str = "world"; owned_string.push_str(borrowed_string); println!("{}", owned_string); }
Here we have our own line, which we can change. This is effective because it potentially allows us to reuse memory allocation. There is a similar case for String and String , since &String can be dereferenced as &str .
fn main() { let mut owned_string: String = "hello ".to_owned(); let another_owned_string: String = "world".to_owned(); owned_string.push_str(&another_owned_string); println!("{}", owned_string); }
After that, another_owned_string remains untouched (note that there is no mut ). There is another option that consumes String but does not require it to be mutable. This is rel = noreferrer> an implementation of the Add trait that takes String as the left side and a &str as the right side:
fn main() { let owned_string: String = "hello ".to_owned(); let borrowed_string: &str = "world"; let new_owned_string = owned_string + borrowed_string; println!("{}", new_owned_string); }
Note that owned_string no longer available after calling + .
What if we want to create a new line, leaving both untouched? The easiest way is to use format! :
fn main() { let borrowed_string: &str = "hello "; let another_borrowed_string: &str = "world"; let together = format!("{}{}", borrowed_string, another_borrowed_string); println!("{}", together); }
Note that both input variables are immutable, so we know that they are not affected. If we want to do the same for any combination of String , we can use the fact that String can also be formatted:
fn main() { let owned_string: String = "hello ".to_owned(); let another_owned_string: String = "world".to_owned(); let together = format!("{}{}", owned_string, another_owned_string); println!("{}", together); }
You do not need to use format! though. You can clone one line and add another line to a new line:
fn main() { let owned_string: String = "hello ".to_owned(); let borrowed_string: &str = "world"; let together = owned_string.clone() + borrowed_string; println!("{}", together); }
Please note - all type specifications I made are redundant - the compiler can output all types in the game here. I added them simply so that they are understandable to newcomers to Rust, since I expect this question to be popular in this group!