Functions
A Rust version of the famous FizzBuzz interview question:
fn main() { fizzbuzz_to(20); // Defined below, no forward declaration needed } fn is_divisible_by(lhs: u32, rhs: u32) -> bool { if rhs == 0 { return false; // Corner case, early return } lhs % rhs == 0 // The last expression in a block is the return value } fn fizzbuzz(n: u32) -> () { // No return value means returning the unit type `()` match (is_divisible_by(n, 3), is_divisible_by(n, 5)) { (true, true) => println!("fizzbuzz"), (true, false) => println!("fizz"), (false, true) => println!("buzz"), (false, false) => println!("{n}"), } } fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted for i in 1..=n { fizzbuzz(i); } }
In FizzBuzz, players take turns to count incrementally, replacing any number divisible by three with the word “fizz”, and any number divisible by five with the word “buzz”, and any number divisible by both 3 and 5 with the word “fizzbuzz”.
-
We refer in
mainto a function written below. Neither forward declarations nor headers are necessary. -
Declaration parameters are followed by a type (the reverse of some programming languages), then a return type.
-
The last expression in a function body (or any block) becomes the return value. Simply omit the
;at the end of the expression. -
Some functions have no return value, and return the ‘unit type’,
(). The compiler will infer this if the-> ()return type is omitted. -
The range expression in the
forloop infizzbuzz_to()contains=n, which causes it to include the upper bound. -
The
matchexpression infizzbuzz()is doing a lot of work. It is expanded below to show what is happening.(Type annotations added for clarity, but they can be elided.)
let by_3: bool = is_divisible_by(n, 3); let by_5: bool = is_divisible_by(n, 5); let by_35: (bool, bool) = (by_3, by_5); match by_35 { // ...