Skip to content
AgileLogics
6 min read

Functions

Prerequisites: Loops

Syntax

fn name(param1: Type1, param2: Type2) -> ReturnType {
    // body
    final_expression
}
  • Functions are declared with fn. Names use snake_case.
  • Every parameter must have a type annotation — Rust never infers parameter types.
  • The return type comes after ->. Leave it out if the function returns nothing (technically it returns (), the empty "unit" value).
  • A function can be defined before or after the code that calls it.

Statements vs expressions

This distinction matters more in Rust than in most languages:

  • A statement performs an action and produces no value, like let x = 5;.
  • An expression evaluates to a value, like 5, a + b, a function call, an if, or a { } block.

Adding a semicolon turns an expression into a statement. That's why the last expression in a function body — written without a semicolon — is the return value. This tail expression is the normal way to return in Rust. The return keyword is used for returning early.

Example

fn main() {
    greet("Ada");

    let total = add(2, 3);
    println!("2 + 3 = {total}");

    println!("area = {}", rectangle_area(4.0, 2.5));
    println!("absolute(-7) = {}", absolute(-7));
    println!("is 10 even? {}", is_even(10));

    let y = {
        let x = 3;
        x * 2 // a block is an expression too
    };
    println!("y = {y}");
}

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

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

fn rectangle_area(width: f64, height: f64) -> f64 {
    width * height
}

fn absolute(n: i32) -> i32 {
    if n < 0 {
        return -n; // early return
    }
    n
}

fn is_even(n: i32) -> bool {
    n % 2 == 0
}

&str is the type of a piece of text such as "Ada" — you'll learn exactly what the & means in the next few lessons.

Expected output

Hello, Ada!
2 + 3 = 5
area = 10
absolute(-7) = 7
is 10 even? true
y = 6

Common mistakes

  • Adding a semicolon to the tail expression:
fn add(a: i32, b: i32) -> i32 {
    a + b;
}
error[E0308]: mismatched types

The compiler explains that the function "implicitly returns () as its body has no tail or return expression" and suggests "remove this semicolon to return this value".

  • Leaving out parameter types. fn add(a, b) -> i32 fails with:
error: expected one of `:`, `@`, or `|`, found `,`
  • Forgetting the -> Type when the function should return a value. Without it, the function returns () and the compiler complains that it found a value where it expected ().

Practice

Write a function celsius_to_fahrenheit that takes an f64 and returns an f64 using the formula c * 9.0 / 5.0 + 32.0. Call it for 100.0 and 37.0, printing each result with one decimal place:

100.0°C = 212.0°F
37.0°C = 98.6°F
Show solution
fn celsius_to_fahrenheit(c: f64) -> f64 {
    c * 9.0 / 5.0 + 32.0
}

fn main() {
    for c in [100.0, 37.0] {
        let f = celsius_to_fahrenheit(c);
        println!("{c:.1}°C = {f:.1}°F");
    }
}