Functions are an important building block in Rust code. They allow you to group reusable code into named blocks, helping to crumble applications into manageable and readable components. This modular approach improves maintainability and promotes the “Don’t Repeat Yourself” (DRY) principle by reducing redundancy.
Define a function in Rust using the fn keyword. The syntax for a function definition generally includes the fn keyword, followed by the function name, a list of parameters in parentheses, an optional return type indicated by ->, and the function body within curly braces {}. The function body contains the code that is executed when the function is called.
Syntax:
fn function_name(param1: type1, param2: type2, ...) -> return_type {
// function block
}
In Rust, the naming convention for functions is called snake_case, which means that all letters are lowercase and underscores are used to separate words. A basic function definition is the main function, which is the entry point of many programs. The “Hello, World!” program validates this:
Example:
fn main() {
// fn keyword, function name, empty parentheses for no parameters
println!( "Hello, world!"); // function body
}
OutPut
Hello, world!
Example:
fn say_hello() { // fn keyword, function name, empty parentheses
println!("Hello, world!"); // function body
}
To call a function, you use its name followed by parentheses (). For example, calling the line function multiple times:
Example:
fn main() {
// fn keyword, function name, empty parentheses for no parameters
say_hello();
say_hello();
say_hello(); // function body
}
fn say_hello() { // fn keyword, function name, empty parentheses
println!("Hello, world!"); // function body
}
Output:
Hello, world!
Hello, world!
Hello, world!
Functions can be defined to have parameters, which are special variables declared as part of the function’s signature. Parameters allow you to pass values into the function when you call it. We refer to these concrete values as arguments, and we use the terms interchangeably. Parameters are defined within the parentheses following the function name and must have their type clearly stated.
Here is an example of a function that takes parameters and prints the sum of two numbers:
Example:
fn print_sum(x: i32, y: i32) { // Parameters x and y with type i32
println!("{} + {} = {}", x, y, x+y);
}
fn main() {
print_sum(3989, 4565); // Calling print_sum with arguments 3989 and 4565
print_sum(35678, 58907); // Calling print_sum with arguments 35678 and 58907
}
Output:
3989 + 4565 = 8554
35678 + 58907 = 94585
Function return type in Rust
Functions can also return values to the code that calls them. The type of the value the function will return is declared after an arrow (->) in the function signature. The value returned by a function is the value of the final expression in the function body’s block. A semicolon ; at the end of an expression turns it into a statement, which does not return a value. Leaving the semicolon off the last expression in the body makes that expression’s value the return value. use the return keyword to return early from a function, specifying a value. While return can be used for the final value, returning the last expression indirectly is considered more natural in Rust.
Example:
fn triple(x: f64) -> f64 { // Declares return type as f64
x / 3. // This is the last expression, its value is returned implicitly
}
fn main() {
let result = triple(17.3); // Call double and assign the returned value
println!("{}", result);
}
Output:
5.766666666666667
If a function does not clearly state a return type, it indirectly returns the unit type (). The compiler can infer this if the return type is lost. By returning structs or collections, functions are able to return multiple values. It is important that every possible return path within a function returns a consistent type.
While the compiler uses type inference within function bodies, type specification is required for function arguments . cannot trust only on type inference for function parameters.
What is a function body in coding?
In Rust, function bodies are the blocks of code enclosed within curly braces {} follow the function’s signature. This block contains the instructions that are executed when the function is called.
Function bodies are composed of a series of statements ending in an expression. Understanding the difference between statements and expressions is important because Rust is an expression-oriented language.
Statements are instructions that perform some action. Critically, statements do not return a value. An example is declaring a variable with let:
let y = 6; // This is a statement
Function definitions themselves are also statements. Any expression followed by a semicolon ; becomes a statement, meaning it will not return a value from the block it’s in.
Expressions evaluate to a resulting value. Most operations in Rust are expressions that return a value. Examples include literals, arithmetic operations (like x * 2.), and function calls return a value. Control flow constructs like if, for, while, and loop can also be expressions with associated blocks return values.
The value a function returns is the value of the final expression in its body. If the body ends with a statement (which has no value), the function indirectly returns the unit type (). To return the value of an expression, you simply omit the semicolon at the end of that expression. You can also use the return keyword to clearly return a value and exit the function early.
A function body consisting only of statements (the println! macro is used in a statement situation here, although macros themselves are a separate concept):
fn say_hello() { // Function signature
// Function body starts here
println!("Hello, world!"); // A statement performing an action
// Function body ends here - implicitly returns ()
}
A function body containing a statement and ending with an expression to return a value:
fn double(x: f64) -> f64 { // Function signature declaring f64 return type
// Function body starts here
let intermediate_value = x; // A statement
intermediate_value * 2. // An expression - its value is returned indirectly
// Function body ends here
}
In the double function, intermediate_value * 2. is an expression. Since it’s the last part of the function body and doesn’t have a semicolon, its evaluated value is returned. If we added a semicolon (intermediate_value * 2.;), it would become a statement, and the function would indirectly return () instead of the calculated f64.
Rust Topics: