Rust Functions
A function is a reusable, named block of code. Instead of writing the same steps over and over, you put them in a function once and call it whenever you need it. You’ve already been using one: main.
Defining and calling a function
Section titled “Defining and calling a function”You define a function with fn, and you call it by writing its name followed by ():
fn greet() { println!("Hello from a function!");}
fn main() { greet(); // call it greet(); // call it again}Output:
Hello from a function!Hello from a function!Parameters: giving a function input
Section titled “Parameters: giving a function input”Functions become useful when you pass them data to work with. These inputs are called parameters. In Rust you must write the type of each parameter:
fn greet(name: &str) { println!("Hello, {name}!");}
fn main() { greet("Alice"); greet("Bob");}Output:
Hello, Alice!Hello, Bob!You can have as many parameters as you need, separated by commas:
fn describe(name: &str, age: u32) { println!("{name} is {age} years old");}
fn main() { describe("Ferris", 10);}Output:
Ferris is 10 years oldThe values you pass in are matched to the parameters by position: the first value goes to name, the second to age. Passing them in the wrong order, like describe(10, "Ferris"), is a compile error, because the types don’t match.
Returning a value
Section titled “Returning a value”A function can hand a value back to whoever called it. You declare the return type after an arrow ->:
fn add(a: i32, b: i32) -> i32 { a + b}
fn main() { let sum = add(3, 4); println!("3 + 4 = {sum}");}Output:
3 + 4 = 7The semicolon rule (important!)
Section titled “The semicolon rule (important!)”Notice that a + b in the example above has no semicolon. This is a key Rust idea:
- An expression without a semicolon is the value that gets returned.
- Adding a semicolon turns it into a statement that returns nothing.
So this breaks:
fn add(a: i32, b: i32) -> i32 { a + b; // ❌ the semicolon means "return nothing" — but we promised an i32}The compiler will complain that the function should return an i32 but doesn’t. Just remove the semicolon on the final line.
Putting it together
Section titled “Putting it together”fn square(n: i32) -> i32 { n * n}
fn main() { let result = square(5); println!("5 squared is {result}");}Output:
5 squared is 25Practice
Section titled “Practice”1. Celsius to Fahrenheit
Section titled “1. Celsius to Fahrenheit”Write a function to_fahrenheit that takes a temperature in Celsius as an f64 and returns it in Fahrenheit. The formula is c * 9.0 / 5.0 + 32.0. Call it for 0, 100 and 37 degrees. Hint: the signature is fn to_fahrenheit(c: f64) -> f64, and the body is a single expression with no semicolon.
Show solution
fn to_fahrenheit(c: f64) -> f64 { c * 9.0 / 5.0 + 32.0}
fn main() { println!("0°C is {}°F", to_fahrenheit(0.0)); println!("100°C is {}°F", to_fahrenheit(100.0)); println!("37°C is {}°F", to_fahrenheit(37.0));}Output:
0°C is 32°F100°C is 212°F37°C is 98.6°FNotice we pass 0.0, not 0. The parameter is an f64, and Rust won’t silently turn an integer into a float for you. When an f64 has no fractional part, {} prints it without the .0, which is why you see 32 and not 32.0.
2. The largest of three
Section titled “2. The largest of three”Write a function largest(a: i32, b: i32, c: i32) -> i32 that returns the biggest of its three numbers. Test it with (3, 9, 4) and (-2, -8, -5). Hint: if is an expression in Rust (see If…Else), so an if / else if / else chain can be the last line of the function.
Show solution
fn largest(a: i32, b: i32, c: i32) -> i32 { if a >= b && a >= c { a } else if b >= c { b } else { c }}
fn main() { println!("{}", largest(3, 9, 4)); println!("{}", largest(-2, -8, -5));}Output:
9-2None of the branches end with a semicolon. Each one is an expression, the whole if chain gives back one of them, and that becomes the return value. Using >= instead of > makes sure ties still return a value.
- Define functions with
fn, call them withname(). - Parameters are inputs; each one needs a type:
fn greet(name: &str). - Declare a return type with
-> Type. - The last expression without a semicolon is the return value.
return value;works too, but is usually only used for early returns.
Quick check
Section titled “Quick check”Quick check
1. In Rust, do you need to write the type of each function parameter?
2. How do you declare a function's return type?
3. What makes a + b (no semicolon) at the end of a function become its return value?
4. Does it matter whether you define a function above or below where it's called (e.g., above or below main)?
Score: 0 / 4
Read more
Section titled “Read more”- Functions — The Rust Book: the official chapter on parameters, return values, and statements versus expressions.
- Statements and Expressions — The Rust Book: a closer look at the idea behind the semicolon rule.
- Functions — Rust by Example: runnable examples, including early
returnand functions that return nothing. - Functions — The Rust Reference: the exact rules for how functions are defined, for when you want the fine print.
- The
fnkeyword — standard library docs: a short summary of function syntax with examples.