Functions
Declaring Functions
Section titled “Declaring Functions”Use fn to declare a function. Every parameter must have an explicit type annotation — the compiler does not infer parameter types. The return type follows ->.
fn add(a: i32, b: i32) -> i32 { a + b}Functions can be defined before or after they are used — Rust does not require forward declarations.
Statements vs Expressions
Section titled “Statements vs Expressions”This is the most important distinction in Rust function bodies:
- A statement performs an action and does not produce a value.
let x = 5;is a statement — it ends with a semicolon. - An expression evaluates to a value.
5 + 3is an expression. Blocks{ ... }are expressions too.
fn main() { // This is a statement — no value produced let y = 6;
// This is an expression block — produces 12 let z = { let x = 3; x * 4 // no semicolon — this is the block's value };
println!("y={}, z={}", y, z);}Adding a semicolon to the last line of a block converts it from an expression to a statement — the block now returns the unit type () instead of the computed value.
The Trailing-Expression Return
Section titled “The Trailing-Expression Return”The last expression in a function body — written without a semicolon — is the return value. You can also use the return keyword for early returns, but idiomatic Rust prefers the trailing expression for the main return path.
fn square(n: i32) -> i32 { n * n // returned because it has no semicolon}
fn max_of_two(a: i32, b: i32) -> i32 { if a > b { a } else { b } // if is an expression}The Unit Type
Section titled “The Unit Type”Functions that do not return a meaningful value implicitly return () (the unit type). The signature fn foo() is shorthand for fn foo() -> (). The unit type is similar to void in other languages but is a real type with exactly one value: ().
fn greet(name: &str) { // implicitly returns () println!("Hello, {}!", name);}fn add(a: i32, b: i32) -> i32 { a + b // trailing expression -- no semicolon -- is the return value}
fn describe(n: i32) -> &'static str { if n > 0 { "positive" } else if n < 0 { "negative" } else { "zero" }}
fn unit_example() { // Functions without -> return the unit type () println!("unit example");}
fn main() { let sum = add(3, 4); println!("add(3, 4) = {}", sum);
println!("describe(10) = {}", describe(10)); println!("describe(-3) = {}", describe(-3)); println!("describe(0) = {}", describe(0));
unit_example();}Compiling…