Sessions 1–3 built up variables and data types; now we can combine values and control execution. Rust defines functions with fn, and because it is expression-oriented, if blocks or plain {} blocks can return values. Session 4 covers function declarations, expressions versus statements, conditional branching, and the major loop forms.
New terms in this post
- Expression: Any construct that produces a value; in Rust almost everything is an expression.
- Statement: Code that executes but returns no value, such as variable declarations.
- loop: An unconditional infinite loop that you exit with
break. - for loop: A loop that iterates over something implementing
Iterator, like arrays or ranges.
Core ideas
- Functions follow the form
fn name(param: Type) -> ReturnType { ... }. If you omit-> ReturnType, it defaults to()(unit). Parameters must declare their types, so the signature alone tells you what flows through the function. - A block
{}returns the last expression's value, so you must avoid a trailing semicolon when you mean to return that value. ifis itself an expression, so you can dolet grade = if score >= 90 { "A" } else { "B" };.- Start with three loop forms:
loop,while, andfor, plusbreakandcontinuefor fine-grained control.
Code along
1. Function basics
fn main() {
greet("Mathbong");
let doubled = double(21);
println!("Double: {doubled}");
}
fn greet(name: &str) {
println!("안녕하세요, {name}!");
}
fn double(value: i32) -> i32 {
value * 2 // no semicolon: expression returns the value
}
Add a semicolon to the final line of double and you will return () instead, causing a type error. Remember: expressions return values, statements do not.
Compare the following two functions:
fn add_ok(a: i32, b: i32) -> i32 {
a + b
}
fn add_wrong(a: i32, b: i32) -> i32 {
a + b;
0
}
The first returns a + b directly. The second turns a + b; into a statement (no return), so you must write a separate final value.
2. Expressions vs. statements
fn main() {
let statement = {
let helper = 2;
helper * 3
}; // block expression → value 6
let condition = true;
let result = if condition { 10 } else { 0 };
println!("statement = {statement}, result = {result}");
}
Blocks return their last expression, and if expressions require every branch to return the same type.
3. if conditionals
fn main() {
let score = 87;
if score >= 90 {
println!("Grade A");
} else if score >= 80 {
println!("Grade B");
} else {
println!("Grade C or below");
}
}
Rust requires a bool condition. Patterns like if score from Python are not allowed.
4. Loops
fn main() {
let mut count = 0;
loop {
count += 1;
if count == 3 {
println!("Exiting loop");
break;
}
}
let mut n = 3;
while n > 0 {
println!("while: {n}");
n -= 1;
}
let numbers = [10, 20, 30];
for value in numbers {
println!("for: {value}");
}
}
loopruns forever until youbreak. Usebreak value;to exit and return a value to bind later.whileruns as long as the condition stays true.foriterates over anything implementingIntoIterator. Ranges like0..5cover 0 through 4, while1..=5includes 5.
Why it matters
- You need functions and flow control to reason about ownership at function boundaries later.
- Thinking in expressions makes
if,match, and block returns feel natural and sets you up for the?operator and closures. - Loop patterns provide reference points before you graduate to iterators and pattern matching.
Practice in CodeSandbox
The sandbox below uses CodeSandbox's Rust starter. Move the main code into src/main.rs, then compare cargo check and cargo run so you can read the compiler feedback beside the final output.
💬 댓글
이 글에 대한 의견을 남겨주세요