Rust Functions

A function is a named block of code that performs a specific task. You write a function once and call it from many places in your program. Functions help you organize code, avoid repetition, and make your program easier to understand.

Defining a Function

Use the fn keyword to define a function:

fn greet() {
    println!("Hello from a function!");
}

fn main() {
    greet();
}

Output:

Hello from a function!

The function greet does one thing: it prints a line. The main function calls greet using its name followed by parentheses.

The Button Diagram

fn greet() { ... }   ← You define the button once

main():
  greet();           ← You press the button
  greet();           ← Press again — same button works again
  greet();           ← Press a third time

Function Parameters

Parameters let you pass data into a function. You list them inside the parentheses when defining the function. Each parameter needs a name and a type.

fn greet_person(name: &str) {
    println!("Hello, {}!", name);
}

fn main() {
    greet_person("Alice");
    greet_person("Bob");
}

Output:

Hello, Alice!
Hello, Bob!

The word "parameter" describes the variable in the function definition. The word "argument" describes the actual value you pass when calling the function. Many developers use these words interchangeably.

Multiple Parameters

Separate parameters with commas. Every parameter must have its type declared:

fn add(x: i32, y: i32) {
    println!("{} + {} = {}", x, y, x + y);
}

fn main() {
    add(3, 7);
    add(10, 20);
}

Output:

3 + 7 = 10
10 + 20 = 30

Return Values

A function can send a value back to the caller. Write the return type after an arrow -> in the function signature. The last expression in the function body is the return value — no return keyword or semicolon needed at the end.

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn main() {
    let result = add(5, 3);
    println!("Result: {}", result);
}

Output:

Result: 8

Notice that x + y has no semicolon. In Rust, an expression without a semicolon at the end of a function automatically becomes the return value. This is called an implicit return.

Explicit Return

You can also use the return keyword to return early from a function:

fn is_positive(n: i32) -> bool {
    if n > 0 {
        return true;
    }
    false
}

The Vending Machine Diagram

fn add(x: i32, y: i32) -> i32

[ Input slot: x=5, y=3 ]
         ↓
[ Machine processes: 5 + 3 ]
         ↓
[ Output slot: 8 ]         ← return value

Expressions vs Statements

This distinction matters a lot in Rust functions.

Statement

A statement performs an action but does not produce a value. It ends with a semicolon.

let x = 5;    ← Statement: assigns a value, produces nothing

Expression

An expression evaluates to a value. It does not end with a semicolon when used as a return value.

5 + 3         ← Expression: evaluates to 8

The Semicolon Trap

fn add(x: i32, y: i32) -> i32 {
    x + y;    ← Bug! Semicolon turns expression into statement.
              ← Function now returns nothing (the unit type ())
              ← Compiler error: expected i32, found ()
}

fn add(x: i32, y: i32) -> i32 {
    x + y     ← Correct: no semicolon, returns the value
}

Functions Calling Other Functions

Functions can call other functions freely. The order in which you define them in the file does not matter — Rust finds them all:

fn square(n: i32) -> i32 {
    n * n
}

fn sum_of_squares(a: i32, b: i32) -> i32 {
    square(a) + square(b)
}

fn main() {
    println!("{}", sum_of_squares(3, 4));
}

Output:

25

Function Naming Style

Rust functions use snake_case — all lowercase letters with underscores between words:

fn calculate_total_price() { }   ← Good
fn CalculateTotalPrice() { }     ← Works but not Rust style
fn calc() { }                    ← Too short, unclear

Unit Return Type

When a function does not return a value, it returns the unit type (). This is like "nothing." You do not need to write it — leaving out the -> arrow means the function returns () automatically.

fn print_hello() {            ← Returns ()
    println!("Hello");
}

fn print_hello() -> () {      ← Same thing, written explicitly
    println!("Hello");
}

Quick Reference

fn name() { }                    ← Function with no params, no return
fn name(x: i32) { }             ← Function with one parameter
fn name(x: i32) -> i32 { x }   ← Function that returns a value
fn name() -> bool { true }      ← Implicit return of last expression

Leave a Comment