- Write functions with parameters and return values
- Tell expressions from statements and explain the role of the semicolon
- Use
ifas an expression - Write
loop,whileandforloops with ranges
A tea recipe is made of named steps such as “boil the water”, “warm the teapot” and “let the tea brew”. Some steps depend on a condition (“if the water is boiling…”), and others repeat (“pour into every glass”). Programs are built the same way: named steps are functions, decisions are **if, and repetition is done with loops**.
Functions
A function is declared with the fn keyword, and its name is written in snake_case. The type of every parameter must be given. If the function returns a value, its type is written after the -> arrow. The order of functions in the file does not matter: main can call a function declared below it.
fn main() {
greet("Leyla");
let a = area(3, 4);
println!("Area: {a}");
}
fn greet(name: &str) {
println!("Hello, {name}!");
}
fn area(width: u32, height: u32) -> u32 {
width * height
}Hello, Leyla! Area: 12
&str is a text type (we will study it in detail in lesson 4). There is no return in area: the last expression, width * height, is returned automatically.Expressions and statements
An expression is code that is evaluated and produces a value: 5 + 3, area(2, 3), a { } block, an if. A statement performs an action but produces no value: let x = 5; or any line ending in ;. Putting ; after an expression turns it into a statement.
fn main() {
let y = {
let x = 3;
x * x + 1
};
println!("y = {y}");
}y = 10
x * x + 1 has no ; at the end.fn square(x: i32) -> i32 {
x * x;
}fn square(x: i32) -> i32 {
x * x
}; turned the expression into a statement, so the function returns nothing — the empty type (). The compiler expected i32 and suggests removing the semicolon.error[E0308]: mismatched types
--> src/main.rs:1:22
|
1 | fn square(x: i32) -> i32 {
| ------ ^^^ expected `i32`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
2 | x * x;
| - help: remove this semicolon to return this valueif is an expression
In Rust, an if condition needs no parentheses, but the curly braces are required. The condition must be of type bool. if is also an expression: you can store its result in a variable or return it from a function. For that, all branches must produce values of the same type.
fn grade(score: u32) -> char {
if score >= 90 {
'A'
} else if score >= 70 {
'B'
} else {
'C'
}
}
fn main() {
let temperature = 28;
let clothes = if temperature > 25 { "T-shirt" } else { "jacket" };
println!("Wear a {clothes}");
println!("95 -> {}", grade(95));
println!("72 -> {}", grade(72));
println!("40 -> {}", grade(40));
}Wear a T-shirt 95 -> A 72 -> B 40 -> C
Loops: loop, while, for
Rust has three loops. loop repeats forever until it is stopped with break, and break can also return a value. while runs as long as a condition is true. for walks through the elements of a collection or a range one by one — it is the most used and the safest loop.
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 5 {
break counter * 10;
}
};
println!("result = {result}");
let mut n = 3;
while n > 0 {
println!("{n}...");
n -= 1;
}
println!("Liftoff!");
}result = 50 3... 2... 1... Liftoff!
fn main() {
for i in 1..4 {
print!("{i} ");
}
println!();
for i in (1..=3).rev() {
print!("{i} ");
}
println!();
let cities = ["Baku", "Ganja", "Shaki"];
for (index, city) in cities.iter().enumerate() {
println!("{index}: {city}");
}
let total: i32 = (1..=100).sum();
println!("1 + 2 + ... + 100 = {total}");
}1 2 3 3 2 1 0: Baku 1: Ganja 2: Shaki 1 + 2 + ... + 100 = 5050
print! prints without a line break, and an empty println!() moves to a new line. enumerate() pairs each element with its index.| Syntax | Values | Note |
|---|---|---|
1..4 | 1, 2, 3 | end excluded |
1..=4 | 1, 2, 3, 4 | end included |
(1..4).rev() | 3, 2, 1 | reversed |
(0..10).step_by(3) | 0, 3, 6, 9 | with a step |
In nested loops, break stops only the innermost loop. To stop the outer loop, give it a label starting with an apostrophe and write break 'label:
fn main() {
'outer: for row in 1..=3 {
for col in 1..=3 {
if row * col == 4 {
println!("found at ({row}, {col})");
break 'outer;
}
}
}
println!("search finished");
}found at (2, 2) search finished
Key points
- Functions are declared with
fn; parameter types are required, and the return type follows->. - An expression produces a value, a statement does not; a trailing
;turns an expression into a statement. - The last expression without
;is the value of a function or block. ifis an expression, and its condition must be abool.loopcan return a value withbreak;forworks with ranges:1..4excludes the end,1..=4includes it.
Check yourself
10 questions. Every correct answer earns XP.