Functions in Rust

Get familiar with Rust’s syntax by programming the first function.

Now, let’s familiarize ourselves with Rust’s essential syntax by writing a set of functions using the Rust compiler. This initial step will provide a foundation for understanding the language's basic semantics.

Press + to interact

Declaring functions in Rust

Let’s get started with the main() function.

Press + to interact
fn main() {
println!("Hello, world!");
}

This is a normal function, which, if you have experience with programming, is a conventional one that is written for every programming language when starting off. It includes a simple println! macro, which prints the string "Hello, world!” to the terminal.

Note: In Rust, Macros are a way to define and reuse patterns of code at compile time. Macros are invoked using the exclamation mark (!). We can also use the exclamation mark to distinguish a macro from a regular function.

Let’s create another function called add_five. This function will take an integer argument and, as the name suggests, add five to it. The function will look like this:

Press + to interact
fn add_five(num: u32) -> u32 {
let add_num = 5;
let new_num = num + add_num;
return new_num;
}

Now, let’s take a moment to see what’s going on here by breaking the function definition into chunks:

  • Line 1: This line contains information about the function definition. We need to look out for a few key components:

    • Whenever we need to define a function, we’ll use the fn keyword. This is followed by the name of the function.

    • Inside the round brackets, after the function name, we denote the arguments that the function will take. In this case, the add_five() function takes one argument of type u32 which we'll call num.

    • We use a right arrow (->) to specify the type that the function will return. In this case, the add_five() function will return an unsigned integer of 32 bits, denoted by u32.

  • Lines 2–4: These lines contain the function body, which is enclosed using curly brackets.

    • We create a new variable named add_num and assign it the value 5.

    • In the next line, we'll add the two numbers and store the value in new_num.

    • We then finally return new_num.

Note: In Rust, if we don't specify variable types explicitly, the compiler will often infer the types based on the context and usage of the variables. Rust's type inference system is powerful and helps ensure type safety without requiring explicit type annotations in many cases. It is also a good practice to specify types.

Another way of returning values from a function in Rust can be as follows:

Press + to interact
fn add_five (num: u32) -> u32 {
num + 5
}

This time around, we do not create a variable to store the value, 5. Instead, we add 5 as a constant to num and returning it. In Rust, the function will return the value returned by the last statement in the function even if we do not use the return keyword provided that the statement doesn’t have a semi-colon (;) at the end.

Now, let’s have a look at how we can use add_five() in the main() function:

Press + to interact
fn add_five(num: u32) -> u32 {
let add_num = 5;
let new_num = num + add_num;
return new_num;
}
fn main() {
let x: u32 = 5;
let y = add_five(x);
println!("{}", y);
}

In the main() function above,

  • Line 8: We declare a variable, x, and assign it a value of 5.

  • Line 9: We then pass the variable, x, to the add_five() function that we created, and the value returned by the function is stored in the variable, y.

  • Line 10: We then print y using the println! macro.

Note: We can't call the add_five() function without the main() function because when the compiler runs a Rust program, it runs the code inside the main() function. Hence it is important to include the functions that we want to call inside the main() function.

Variable declarations in Rust

Let’s talk a little about how variables are declared in Rust. As we saw above, we used the let keyword to declare our variables. In JavaScript or TypeScript, we use the let keyword as opposed to the const keyword, which is used to declare constant variables that cannot be changed after initialization. However, in Rust, we use only the let keyword to declare variables.

An interesting fact: All declared variables in Rust are immutable by default. This means that when they’re declared, their values cannot be altered unless specified otherwise. To declare variables with a mutable value, we have to use let with the mut keyword.

Let’s have a short look at how we can achieve this:

Press + to interact
fn main() {
let x: u32 = 10;
x += 10;
println!("{}", x);
}

Notice that when we try to change the value of x, we get an error stating that we cannot change the value because the variable is immutable. Let’s see what happens when we use the mut keyword:

Press + to interact
fn main() {
let mut x: u32 = 10;
x += 10;
println!("{}", &x);
}

As expected, we didn’t get any errors because we declared x to be a mutable variable.

Handling unused variables

Rust is an extremely memory-safe language. This means that even before the program is compiled, Rust will give errors on where the code might go wrong. If we were to use Rust in an IDE such as Visual Studio Code, we’d get all sorts of useful information, such as warnings for unused variables and warnings for another function taking ownership of a variable whose ownership belongs to a function in a different scope.

In case of unused variables, Rust will give us warnings, like so:

Press + to interact
fn main() {
let x: u32 = 50;
println!("No variables being used.");
}

We can see even though the code runs and we get our output, Rust gives us a warning that the variable we declared is not being used. We can deal with that by prepending an underscore before the variable name, as shown below:

Press + to interact
fn main() {
let _x: u32 = 50;
println!("No variables being used.")
}

Generally, it is a good practice to not declare variables in the first place if they’re not to be used but in case it is absolutely necessary, Rust provides the users with the mechanism, as discussed above.