Functions
Rust functions are typed end-to-end. Parameters declare types; the return type follows ->. The last expression (no semicolon) is the return value — idiomatic Rust uses this heavily.
Signatures + expressions + early return
EXAMPLE
// Basic
fn add(a: i32, b: i32) -> i32 {
a + b // no semicolon — this expression is the return value
}
// Early return
fn safe_div(a: f64, b: f64) -> Option<f64> {
if b == 0.0 {
return None;
}
Some(a / b)
}
// Multiple returns via tuple
fn divmod(a: i32, b: i32) -> (i32, i32) {
(a / b, a % b)
}
let (q, r) = divmod(17, 5);
// Generic + trait bound
fn largest<T: PartialOrd + Copy>(xs: &[T]) -> T {
let mut best = xs[0];
for &x in xs.iter().skip(1) {
if x > best { best = x; }
}
best
}
// Closures — anonymous functions, capture environment
let add5 = |x| x + 5;
let vec = vec![1, 2, 3];
let sum: i32 = vec.iter().map(|&x| x * 2).sum();
// Function pointers / higher-order
fn apply(f: fn(i32) -> i32, x: i32) -> i32 { f(x) }
println!("{}", apply(|n| n + 1, 9)); // closures that don't capture coerce to fn
Why it matters
Functions are expressions all the way down. Avoid return at the bottom — let the last expression be the value. It’s shorter and matches the way Rust is written everywhere.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
fn add(a: i32, b: i32) -> i32 {
a + b // no semicolon = return
}
fn main() { println!("{}", add(2, 3)); }
Try it Yourself »
Exercise
Return-type arrow syntax.
fn add(a: i32, b: i32)
i32 { a + b }
Two characters.
Discussion
Loading…