Beginner · Types, control flow and functions · topic 7 of 50 · 25 min
Functions, statements and expressions
Explanation
Why functions?
A function is a named block of code that does one job. You write it once and call it many times, with different inputs. You already know main. Rust uses snake_case names and you can define functions in any order in the file.
fn main() {
greet("Meena");
let total = add(250, 120);
println!("Total: {total}");
}
fn greet(name: &str) {
println!("Namaste, {name}!");
}
fn add(a: i32, b: i32) -> i32 {
a + b
}Parameters always need types
Parameters are the inputs a function takes. In Rust you must write the type of every parameter, even when it seems obvious. This is a deliberate choice: the function's signature (its first line) then fully describes how to call it, and the compiler can check every call.
Statements and expressions
This idea is small but it explains much of Rust. A statement does something and gives back no value. let x = 5; is a statement. An expression is evaluated to a value. 5 + 6 is an expression, a call like add(1, 2) is an expression, and even a block in curly braces is an expression: its value is its last line, if that line has no semicolon.
let fee = {
let base = 1000;
let gst = base * 18 / 100;
base + gst // no semicolon: this is the block's value
};
println!("{fee}"); // 1180Returning values
The return type is written after an arrow ->. The value of the last expression in the body is returned automatically. Use the return keyword only to leave early, for example inside an if.
fn discount(amount: u32) -> u32 {
if amount < 500 {
return 0; // early exit
}
amount / 10 // the normal result
}The famous semicolon mistake
fn square(n: i32) -> i32 {
n * n;
}
// error[E0308]: mismatched types
// expected `i32`, found `()`
// help: remove this semicolon to return this valueRead that message slowly: the function promised an i32, but the body ended with a statement, so it produced the unit type (). The compiler even tells you which semicolon to remove.
Functions that return nothing
If you leave out -> and a type, the function returns (), the unit type. That is what greet above does. A function can also never return at all, written -> !, but you will rarely write that yourself.
Common mistakes
- Forgetting parameter types: fn add(a, b) does not compile. Write fn add(a: i32, b: i32).
- A semicolon after the last expression of a function with a return type: remove it.
- Using return everywhere. It works, but idiomatic Rust uses the last expression and keeps return for early exits.
- Passing the wrong number type: add(5u8, 3) when add takes i32. Convert first or change the signature.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Functions, statements and expressions · 1/7
fn add(a: i32, b: i32) -> i32 {
a + b
}Functions in Rust start with fn. Every parameter has a type, and the return type comes after an arrow.
Prefer a video by a teacher? Find free videos on “rust functions statements expressions return value” on YouTube ↗
In real life: An EMI calculator for a loan app
A loan comparison website shows the monthly EMI for a car loan. The formula is put in one function with clear typed parameters, so every page that needs an EMI calls the same tested code. The function ends with the formula as its last expression.
fn emi(principal: f64, yearly_rate_percent: f64, months: i32) -> f64 {
let r = yearly_rate_percent / 12.0 / 100.0;
let factor = (1.0 + r).powi(months);
principal * r * factor / (factor - 1.0)
}
fn main() {
let monthly = emi(500_000.0, 9.0, 60);
println!("EMI: Rs {:.2}", monthly);
}Practice (0/3 done)
What does this print? fn f(x: i32) -> i32 { let y = x + 1; y * 2 } fn main() { println!("{}", f(4)); }
Why does this not compile? fn half(n: i32) -> i32 { n / 2; }
Write three functions: is_adult(age: u32) -> bool, with_gst(price: u32) -> u32 (adds 18 percent), and grade(marks: u32) -> char (A for 90+, B for 75+, C for 40+, F otherwise). Call each from main and print the results.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Control flow: if, loop, while and forTypes, control flow and functions · same module
- Scalar types: numbers, bool and charTypes, control flow and functions · same module
- FunctionsKotlin and Android App Development · Null safety, functions and lambdas
- Functions: declarations, expressions and returnJavaScript Programming (language in depth) · Functions and closures
- Functions: declare, define, call and returnC++ Programming (modern C++ and DSA) · Decisions, loops and functions
- FunctionsFrontend Web Development · JavaScript basics
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Which function signature is valid Rust?
Answer: fn add(a: i32, b: i32) -> i32
Each parameter is name: type, and the return type follows ->.
What does a function without -> return?
Answer: The unit type ()
Without a return type, the function returns ().
Which of these is an expression?
Answer: x + 1
x + 1 produces a value. The others are statements or items.
What is the value of this block? { let a = 2; a * 3 }
Answer: 6
The last line a * 3 has no semicolon, so the block's value is 6.
When should you use the return keyword?
Answer: Only for early exits; the last expression returns automatically
Idiomatic Rust ends with an expression and uses return for leaving early.
Which is a valid single-expression function?Related
Answer: fun double(x: Int) = x * 2
Use = with an expression; parameter types are required.
From Functions
What does a function return if it has no return statement?Related
Answer: undefined
Every JavaScript function without a return value gives undefined.
What does void as a return type mean?Related
Answer: The function returns nothing
void functions do their job without giving a value back.
What does a function return if it has no return statement?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Types, control flow and functions” before its exam: Control flow: if, loop, while and for, Mini project: reading input from the user.
- Module 2 exam: Types, control flow and functions · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Ownership: Rust's big idea. 50 topics left in the course before the final exam.