Step 6 of 6
Building functions from functions
Real programs are built from small functions that call each other. Each one does one job and has a clear name; bigger functions combine them.
fn square(x: i32) -> i32 {
x * x
}
fn sum_of_squares(a: i32, b: i32) -> i32 {
square(a) + square(b)
}
fn is_right_triangle(a: i32, b: i32, c: i32) -> bool {
sum_of_squares(a, b) == square(c)
}
fn main() {
println!("{}", sum_of_squares(3, 4));
println!("{}", is_right_triangle(3, 4, 5));
println!("{}", is_right_triangle(2, 3, 4));
}
25
true
false
Each call runs to completion and its value takes the place of the call. is_right_triangle(3, 4, 5) calls sum_of_squares(3, 4), which calls square(3) and square(4) and adds 9 and 16; then square(5) gives 25, and 25 == 25 is true.
Behind the scenes, Rust keeps a call stack: the list of functions currently running, each with its own parameters and variables. A call adds an entry; a return removes it, and that function's variables are gone. When a program panics, the backtrace you can ask for is a printout of this stack.
is_right_triangle returns a bool: a comparison is an expression, so it can be the final expression. Functions that answer a yes/no question are usually named is_..., has_... or can_....
Each function has its own variables
A variable in one function isn't visible in another. Pass the value as an argument instead:
fn show_bonus() {
println!("bonus: {}", score * 2);
}
fn main() {
let score = 10;
show_bonus();
println!("{score}");
}
error[E0425]: cannot find value `score` in this scope
--> src/main.rs:2:27
|
2 | println!("bonus: {}", score * 2);
| ^^^^^ not found in this scope
The fix is fn show_bonus(score: i32) and calling show_bonus(score). Constants are the exception: a const at the top of the file is visible in every function.
At work
- Write the small helper first, check that it works, then build on it.
- A function's name, parameter names and types are its first documentation:
fn net_price(gross_cents: u32, tax_percent: u32) -> u32says far more thanfn calc(a: u32, b: u32) -> u32. - Comments starting with
///above a function are doc comments:cargo docturns them into documentation pages, and editors show them when you hover over a call.
/// Returns the area of a rectangle, in square meters.
fn area(width: u32, height: u32) -> u32 {
width * height
}
Your task
A game scores each round from two parts. Write three functions:
fn kill_points(kills: u32) -> u32: 100 points per kill.fn time_bonus(seconds_left: u32) -> u32: 2 points per second left.fn total_score(kills: u32, seconds_left: u32) -> u32: the sum of the two, computed by calling the other two functions.
Challenge 2
Write fn is_even(n: i32) -> bool, then fn is_odd(n: i32) -> bool that answers by calling is_even and flipping the result with !.
Challenge 3
Write fn max_of_two(a: i32, b: i32) -> i32 that returns the larger number (use an early return), and then fn max_of_three(a: i32, b: i32, c: i32) -> i32 that finds the largest of three by calling max_of_two twice.