← Back to Rust series
πŸ¦€
Basics
Basics Β· Prerequisite: lesson 04

05. Functions, Expressions, Return Values, Doc Comments

Defining functions with `fn name(arg: T) -> R { ... }`, the distinction between expressions and statements, returning implicitly via the last expression vs. explicit `return`, and `///` doc comments that turn into HTML via `cargo doc`. This lesson sets you up to write idiomatic functional Rust.

Rustfunctionsfnexpressionreturndocumentationcargo doc
Duration
⏱ ~1 hour
Level
πŸ“Š Beginner
Prerequisite
🎯 Lesson 04
OUTCOME
Defining functions with `fn name(arg: T) -> R { ... }`, the distinction between expressions and statements, returning implicitly via the last expression vs. explicit `return`, and `///` doc comments that turn into HTML via `cargo doc`. This lesson sets you up to write idiomatic functional Rust.

What you'll learn

  • 1Define functions with explicit parameter and return types
  • 2Tell expressions from statements
  • 3Return implicitly from the last expression β€” no explicit `return`
  • 4Write `///` doc comments and build HTML with `cargo doc`
  • 5Return multiple values via tuples

Overview

Rust functions are straightforward, but expression-orientation trips up people from imperative languages β€” **whether you put a semicolon on the last line decides whether anything is returned**. Once that clicks, code gets dramatically shorter.

Core Concepts

1) Function syntax

rust
fn add(a: i32, b: i32) -> i32 {
    a + b   // no semicolon β†’ this is the return value
}

2) Expression vs. statement

  • **Expression** β€” produces a value. `5`, `a + b`, `if cond { 1 } else { 2 }`, blocks `{ let x = 1; x + 1 }`
  • **Statement** β€” performs an action but produces no value. `let x = 5;`, `fn f() {}`
  • Adding a semicolon to an expression turns it into a statement β€” value is discarded

3) Explicit return

Use `return value;` when you want an early exit. For the normal happy path the trailing-expression form is more idiomatic.

4) Doc comments

  • `///` declares documentation for the next item
  • Markdown is supported β€” code blocks become automatic doctests
  • `cargo doc --open` generates and opens HTML docs

Hands-on Examples

Implicit return alongside explicit `return`:

rust
fn divide(a: i32, b: i32) -> i32 {
    if b == 0 {
        return -1;     // early exit
    }
    a / b             // last expression β†’ returned
}

fn main() {
    println!("{}", divide(10, 3)); // 3
    println!("{}", divide(10, 0)); // -1
}

Return multiple values via a tuple:

rust
fn minmax(v: &[i32]) -> (i32, i32) {
    let mut mn = v[0];
    let mut mx = v[0];
    for &x in v {
        if x < mn { mn = x; }
        if x > mx { mx = x; }
    }
    (mn, mx)
}

fn main() {
    let (a, b) = minmax(&[3, 7, 1, 9, 4]);
    println!("min={}, max={}", a, b); // 1, 9
}

Doc comments β€” Markdown + doctest:

rust
/// Add two numbers and return the sum.
///
/// # Examples
///
/// ```
/// assert_eq!(my_crate::add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}
bash
cargo doc --open       # generate and open HTML docs
cargo test --doc        # run doctests

Common Mistakes

Q. My return value disappeared β€” I wrote `a + b` and got nothing back

A. `a + b;` (with semicolon) is a statement, the value is dropped. The trailing expression must have **no semicolon**.

Q. What's the unit type `()`?

A. Roughly equivalent to `void` elsewhere. Omitting the return type means `-> ()` β€” the function returns no meaningful value.

Q. Can main return a value?

A. Yes β€” `fn main() -> Result<(), Box<dyn Error>>` enables `?` inside main. Covered in the error-handling lessons.

Recap

  • Function signatures spell out parameter and return types
  • Last expression is the return value β€” semicolon turns it into a statement
  • Use `return` for early exits
  • /// doc comments become HTML via `cargo doc`, doctests run via `cargo test --doc`

Try It Yourself

  1. Write Celsius ↔ Fahrenheit converter functions and call them from main
  2. Write a `stats` function returning `(i32, i32, f64)` for min / max / mean
  3. Add a /// example block and run `cargo test --doc` to verify the doctest passes
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub β†—