Day 4 of Reading “The Rust Book” Cover to Cover: Functions & Expressions

 

Rust Logo

Functions are declared with the fn keyword. Rust doesn't care where you define them, before or aftermain(), as long as they're defined somewhere.

Function Basics

fn main() {
greet();
greet(); // Can call it multiple times
}
fn greet() {
println!("Hello!");
}

Output:

Hello!
Hello!

Parameters

Functions can take parameters. You must declare the type of each parameter.

fn add(a: i32, b: i32) {
println!("Sum: {}", a + b);
}
fn main() {
add(5, 3); // ✅ Sum: 8
}

Return Values

Functions can return values using the -> syntax. The last expression in a function is automatically returned (no semicolon).

fn add(a: i32, b: i32) -> i32 {
a + b // ✅ Returns the result (no semicolon)
}
fn main() {
let result = add(5, 3);
println!("Result: {}", result); // 8
}

Important: If you add a semicolon, it becomes a statement and returns nothing (unit type ()).

fn add(a: i32, b: i32) -> i32 {
a + b; // ❌ Error: expected i32, found ()
}

Statements vs Expressions

Statements are instructions that perform an action but don’t return a value. They end with a semicolon.

Expressions evaluate to a resulting value that can be returned or assigned. They do NOT end with a semicolon.

fn main() {
let x = 5 + 6; // ✅ Expression: 5 + 6 evaluates to 11

let y = {
let x = 3;
x + 1 // ✅ Expression: evaluates to 4 (no semicolon)
};
println!("y: {}", y); // 4
}

If you add a semicolon to that inner x + 1, it becomes a statement and returns () instead.

let y = {
let x = 3;
x + 1; // ❌ Semicolon makes it a statement, y becomes ()
};

That’s why return values in functions work without semicolons; the last line is an expression.

fn double(x: i32) -> i32 {
x * 2 // ✅ Expression, returns the value
}

Multiple Parameters

fn print_labeled_measurement(value: i32, unit_label: char) {
println!("The measurement is: {value}{unit_label}");
}
fn main() {
print_labeled_measurement(5, 'm'); // ✅ The measurement is: 5m
}

Early Returns

You can return early from a function using the return keyword, but it's not common in idiomatic Rust. Usually, you just use an expression.

fn check(x: i32) -> i32 {
if x < 0 {
return 0; // Early return
}
x + 1 // Normal return
}

Key takeaway for Future Me:

No semicolon = expression = returns value

Semicolon = statement = returns nothing

If your function isn’t returning what you expect, check if you accidentally added a semicolon.

0 comments:

Post a Comment