RustArena

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

/// 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:

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.

Previous: Returning early