Transforming a mutable String into an immutable


#1

Given this code:

#[allow(dead_code)]

fn main() {
    println!("I can show you {}", what03());
}

fn what02() -> String {
    let mut what = "the".to_string();
    what.push_str(" world. - 2.");
    what
}

fn what03() -> String {
    let mut what = "the".to_string();
    what.push_str(" world. - 3.");
    what.split_at(what.len()).0.to_string()
}

Am I correct thinking that what02 returns a mutable String and what03 returns an immutable String?

Is there a cost to “what.split_at(what.len()).0.to_string()”?

Is there a better way to transform a mutable into an immutable?

Thanks.


#2

Both what02 and what03 return ownership of a String, to do whatever you want with - when it comes to owned values, mutability is a property of the variable binding, not the actual object. For example:

// both immutable
let a = what02();
let b = what03();

// both mutable
let mut c = what02();
let mut d = what03();

You only get to specify the mutability in the return type of your function if you’re returning a reference to (aka borrow of) an object, rather than the object itself.

I may well have not explained this all that well :stuck_out_tongue:


#3

Thanks. Is the returned String “given” to the caller, including the ownership, or is are a, b, c and d (in your example) completely new string?

If we were to look at a map of the memory, would “a” be at the same place in memory where “what” was created? Or is it a copy?


#4

In your example, the following line is creating a new String every time the function gets called:

let mut what = "the".to_string();

The important thing to keep in mind is that when you define a string literal in your source code (such as "the"), its type is &'static str - in other words, a reference to the static string that’s stored in your program. You can’t return ownership of "the" directly, because you don’t own it! So when you call to_string(), you’re effectively copying the contents of that string into a new one that you do own.

This example might make that concept a bit clearer:

// The above line of code is equivalent to this, with explicit type annotations added:
let the: &'static str = "the";
let mut what: String = the.to_string();

Since you’re returning this new string directly rather than holding on to it somewhere and returning a reference, the caller gets ownership of it. This part doesn’t do any copying.

So to answer your question, a, b, c and d are all separate strings, but they’re all owned by main. If you looked at a memory map, "the" and all four of your return values would most likely have separate locations. Does that make sense?