This works:
let hello = "Hello ".to_string();
let world = "world!";
let hello_world = hello + world;
But this doesn't:
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + world;
But this does:
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + &world;
Is that because the String needs a pointer to the original string slice of the second String? If so, why?
The answer is in two parts.
The first part is that + involves using an Add trait implementation. It is implemented only for:
impl<'a> Add<&'a str> for String
Therefore, string concatenation only works when:
String
&str
Note: unlike many other languages, addition will consume the Left Hand Side argument.
The second part, therefore, is what kind of arguments can be used when a &str is expected?
Obviously, a &str can be used as is:
let hello = "Hello ".to_string();
let hello_world = hello + "world!";
Otherwise, a reference to a type implementing Deref<&str> will work, and it turns out that String does so &String works:
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + &world;
And what of other implementations? They all have issues.
impl<'a> Add<String> for &'a str requires prepending, which is not as efficient as appendingimpl Add<String> for String needlessly consume two arguments when one is sufficientimpl<'a, 'b> Add<&'a str> for &'b str hides an unconditional memory allocationIn the end, the asymmetric choice is explained by Rust philosophy of being explicit as much as possible.
Or to be more explicit, we can explain the choice by checking the algorithmic complexity of the operation. Assuming that the left-hand side has size M and the right-hand side has size N, then:
impl<'a> Add<&'a str> for String is O(N) (amortized)impl<'a> Add<String> for &'a str is O(M+N)impl<'a, 'b> Add<&'a str> for &'b str is O(M+N)impl Add<String> for String is O(N) (amortized)... but requires allocating/cloning the right-hand side for nothing.The standard library implements the following:
impl<'a> Add<&'a str> for String
Which is exactly what you have noticed, you can only add a &str to a String.
This has these Advantages:
&str slice&String (as it dereferences to &str)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With