So I’ve been messing with Rust language for a couple of weeks now and I am thoroughly enjoying it. Rust is a systems programming language developed by Mozilla foundation. It’s becoming popular with plenty of rave reviews about seg-fault safety and the modern syntax. I highly recommend taking a look if you haven’t already.
Rust is obsessed about memory from ground up. This is understandable given that avoiding seg-faults is one of its unique selling points. When you write Rust, you are contantly thinking about where things are in memory. Sometimes that makes it very difficult to do some of the most trivial things in programming. Take string concatenation for example.
And in PHP:
So you would think that the following would work in Rust:
That doesn’t compile. This is because Rust has 2 types of strings.
y are of type
&str. These are called
string slices or
static strings. They have a fixed size and cannot be mutated.
A string literal is a string slice that is statically allocated, meaning that it’s saved inside the compiled program, and exists for the entire duration it runs. The reference binding is a reference to this statically allocated string. Any function expecting a string slice will also accept a string literal.
So what about
String? Strings are allocated on the heap and can be mutated. It’s essentially a vector of unicode chars.
Strings are generally created from a
&str by using to_string() function. So lets try again:
That doesn’t work either. It’ll give you
expected &str, found struct
std::string::String. Ok. So how about this then:
Again, the compiler will throw the same error as before. So in order to get around it, you have to dereference one of the
Strings to obtain the
&str version of it. This is done easily by prefixing an ampersand to the second argument, which
essentially dereferences the
String and passes a pointer of the
string slice to the concat function. So the working
version of the previous example would look like this:
If you are making a call to a function that’s returning a
String and you want to concatenate it to an existing string
then you just add the ampersand to the beginning of the function call.
But WTF? why do you have to do that?
The simple answer is because how concatenation is done. When you are using the
+ operator for
Strings in Rust, you are
essentially calling the std::ops::Add Trait on the
String on the
left hand side. And this Trait is designed so that the left hand side argument should be
String and the right hand side
argument should be an
So now we understand that this is because of a particular design decision of the standard library. But why? Why not just
allow for two arguments like
add(a: String, b: String) -> String?
This is basically down to how and where things are stored in the memory and the operational cost of mutating them.
impl<'a> Add<String> for &'a strrequires prepending, which is not as efficient as appending
impl Add<String> for Stringneedlessly consume two arguments when one is sufficient
impl<'a, 'b> Add<&'a str>for &’b str hides an unconditional memory allocation