I have just started with Rust, and I have just reached the end of the section on control flow in the Rust Programming Language Textbook.
I have been playing around with some of the concepts that have been introduced thus far, but I have ran into an issue with strings.
I might be a bit... erm... Rusty (ahem*), but I think in C++ I could do something like:
std::string my_string = "";
my_string = "This is my amazing string.";
With Rust, when I try:
let mut my_string = String::new();
my_str = "This is my amazing string";
I get:
"my_string = "This is my amazing string.";
expected struct `std::string::String`, found reference
help: try using a conversion method: `"This is my amazing string.".to_string()`"
It found a reference, and I need to try converting my_string to a string?
In the examples so far in the textbook, it appears that the original empty string is just shadowed. Something like:
let mut my_string = String::new();
let mut my_string = "This is my amazing string.";
In Listing 2-5 from the textbook, it actually replaces the string with a new string:
let mut guess = String::new();
Everytime it loops back around, but I guess the principle is the same?
Some of these concepts are new to me, so I appreciate your help (I am currently only up to the section on ownership, so any concepts beyond this would not be familiar to me).
*I am aware this pun has probably been used ad nauseum, I apologise profusely.
The issue here is the string literal there has a type &'static str, which is a string slice that lives for the life of the program (all string literals are like that). So what you want is to make that string literal a String, which is a dynamically allocated and an owned value:
let mut my_string = String::new();
my_string = "This is my amazing string".into();
The into() converts the string slice to a String and now the types match up.
Thankyou for the information. This is not something that has come up in the textbook, yet; I am glad to know, however, that it was not something covered already and that I have missed; otherwise I would be going back and re-reading everything!
I'd like to point out an additional nuance: C++ supports copy-assignment and move-assignment operators. Rust's assignment is always a move-assignment operator and is not customizable. @vitalyd's solution is actually equivalent to
std::string my_string = "";
my_string = std::string("This is my amazing string");
where the second line allocates a string whose allocated buffer is transferred to my_string via the C++ r-value/move assignment operator. In the example you provided, this made no practical difference since the string was initially empty/unallocated. However, it makes a difference if my_string already has an allocated buffer.
std::string my_string = "foo";
// Overwrites "foo" using copy-assignment and does not allocate
// additional memory.
my_string = "bar";
// Allocates a new string with "baz" and then replaces my_string's
// pointer to point to it.
my_string = std::string("baz");
The latter is clearly less efficient for this scenario. Here are the rust equivalents so that you can pick as appropriate.
let mut my_string = "foo".to_string();
// Overwrites already-allocated buffer with "bar".
my_string.clear();
my_string.push_str("bar"); // or: my_string += "bar";
// On nightly, these two lines can be replaced with:
my_string.splice(0.., "bar");
// Allocates a new string with "baz" and then replaces my_string's
// pointer to point to it.
my_string = "baz".to_string();