Easy Tutorial
❮ Rust Comments Rust Project Management ❯

Rust Functions

Functions are ubiquitous in Rust.

From previous chapters, you can already understand the basic form of Rust functions:

fn <function_name> ( <parameters> ) <function_body>

Rust function names are styled with lowercase letters separated by underscores:

Example

fn main() {
    println!("Hello, world!");
    another_function();
}

fn another_function() {
    println!("Hello, tutorialpro!");
}

Output:

Hello, world!
Hello, tutorialpro!

Note that we defined another_function after the main function in our source code. Rust does not care where you define your functions, as long as they are defined somewhere.

Function Parameters

In Rust, if a function needs parameters, you must declare both the parameter names and types:

Example

fn main() {
    another_function(5, 6);
}

fn another_function(x: i32, y: i32) {
    println!("The value of x is: {}", x);
    println!("The value of y is: {}", y);
}

Output:

The value of x is: 5
The value of y is: 6

Function Body: Statements and Expressions

Rust function bodies are made up of a series of statements optionally ending in an expression. So far, we've only seen functions without a final expression, but we've already used expressions as parts of statements.

Statements are actions that perform some action and do not return a value. For example:

let a = 6;

This statement does not return a value, so the following is incorrect:

let a = (let b = 2);

Expressions evaluate to a resulting value. Here are some expressions (assuming the identifiers have been defined):

a = 7
b + 2
c * (a + b)

In Rust, you can write a more complex expression within a block enclosed by {}:

Example

fn main() {
    let x = 5;

    let y = {
        let x = 3;
        x + 1
    };

    println!("The value of x is: {}", x);
    println!("The value of y is: {}", y);
}

Output:

The value of x is: 5
The value of y is: 4

Clearly, this program includes an expression block:

{
    let x = 3;
    x + 1
};

And you can use function statements within the block, with the last step being an expression whose value is the value of the entire block. This kind of block is called a function body expression.

Note: There is no semicolon after x + 1, otherwise it would become a statement!

This expression block is a valid function body. Also, in Rust, function definitions can be nested:

Example

fn main() {
    fn five() -> i32 {
        5
    }
    println!("The value of five() is: {}", five());
}

Function Return Values

The previous nested example demonstrated how Rust declares return types: after the parameter list with ->.

In the function body, you can end the function at any time with the return keyword and a suitable value. This is the most familiar approach for most developers:

Example

fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

However, Rust does not support automatic return type deduction! If the return type is not explicitly declared, the function is considered a "pure procedure" and is not allowed to return a value, and return cannot be followed by a return value expression. This is to ensure that public functions form a visible contract.

Note: A function body expression cannot use the return keyword.

❮ Rust Comments Rust Project Management ❯