Hey there! This is my third post in the Rust Series called #RustWorthy. In my last post , we discussed ownership in Rust. This post is an extension of the previous post which includes how ownership happens with functions and we’ll also look at borrowing.
Functions in Rust
Like all other common programming languages, functions are extensive in Rust. The entry point of Rust code is the main method. Let’s look at a simple function in Rust.
The above is a simple program in Rust that prints strings. It has a main function which will be the entry point of the code which prints a string. There’s another function print_another_string which will be called from the main function and this will print another string. Yeah, I get it! This is self-explanatory but I wanted to show a glimpse of a complete Rust code.
Ownership & Functions in Rust
We already spoke about what Ownership is in my last post. That’s how Rust handles its memory allocation at runtime. We also saw that the ownership will be moved/ transferred if you assign a variable to another variable
So, What happens when we pass a variable to a function during a function call? The ownership is transferred to the function and the value will eventually be dropped from memory when the function completes its execution. Thus, the value will not be valid in the scope after the function call. Consider the following,
We have a main method that has an immutable variable s that stores a string, we calculate the length of the string with the help of a function and try to print both the original string and the length of the string. We have a function called calculate_length that returns the length of a string. Now, what happens when we compile this? It won’t!
This is because we no longer have s in memory and it was long dropped when the calculate_length completed its execution.
So, what if you need the value after the function? There are two possible ways, One is to return back the ownership to the calling function.
As you can notice that the function calculate_length returns both the actual string and the length of the string, by which the calling function gets the ownership back of the String s and we’ll get the output without any compilation errors.
But don’t you think that this approach is tedious? That’s where we will be using Borrowing.
Borrowing in Rust
In this approach, you will be passing only the reference &s of the string and not the actual string. So, you let the called function calculate_lengh to borrow the value while keeping the ownership to the calling function.
This will compile without an issue. Like our variables are immutable by default, so does our references. You cannot alter the value. Let’s try it out.
You can pass the reference as a mutable reference and it can be altered that way.
To avoid data races, mutable references comes with a restriction - you can have only one mutable reference to a particular piece of data in a particular scope
Rust does not allow this to prevent any of the following scenarios of data races:
- Two or more pointers access the same data at the same time.
- At least one of the pointers is being used to write to the data.
- There’s no mechanism being used to synchronize access to the data.
That’s it about Ownership in Rust. There’s a lot of interesting things to learn.
“To infinity & Beyond”