Lesson 4

Functions

Learn how to define functions with parameters, return values, and understand expressions vs statements.

Defining Functions

You define functions with fn, followed by the name, parameters in parentheses, and the body in curly braces. Rust uses snake_case for function names by convention. Parameters must have their types declared -- Rust won't guess here.

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

Return Values

To return a value, declare the return type with -> after the parameters. Here's the key insight: in Rust, the last expression in a function is automatically its return value -- no return keyword needed. Just leave off the semicolon.

fn add(a: i32, b: i32) -> i32 {
    a + b  // no semicolon = this is the return value
}

Expressions vs Statements

Statements perform actions but don't return values (like let x = 5;). Expressions evaluate to a value (like 5 + 3 or a block { x + 1 }). Most things in Rust are expressions, which is why functions can return without the return keyword.

Try it

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

    let sum = add(3, 7);
    println!("3 + 7 = {}", sum);

    let result = multiply(4, 5);
    println!("4 * 5 = {}", result);

    let temp_f = celsius_to_fahrenheit(100.0);
    println!("100C = {}F", temp_f);

    let is_even = is_even(42);
    println!("Is 42 even? {}", is_even);

    // Expressions can be used inline
    let y = {
        let x = 3;
        x * x + 1 // no semicolon -- this block returns 10
    };
    println!("Block expression result: {}", y);
}

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

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

fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

fn celsius_to_fahrenheit(c: f64) -> f64 {
    c * 9.0 / 5.0 + 32.0
}

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

Challenge

Write a function called square that takes an i32 and returns its square. Call it from main and print the result.

Previous: Data Types

Next: Control Flow