Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

2.7 Functions and Methods

Functions are defined using the fn keyword, followed by the function name, parameter list (with types), and an optional return type specified after ->.

2.7.1 Function Declaration and Return Values

// Function that takes two i32 parameters and returns an i32
fn add(a: i32, b: i32) -> i32 {
    // The last expression in a block is implicitly returned
    // if it doesn't end with a semicolon.
    a + b
}

// Function that takes no parameters and returns nothing (unit type `()`)
fn greet() {
    println!("Hello from the greet function!");
    // No return value needed, implicit `()` return
}

fn main() {
    let sum = add(5, 3);
    println!("5 + 3 = {}", sum);
    greet();
}

Key Points (Functions):

  • Parameter types must be explicitly annotated.
  • The return type is specified after ->. If omitted, the function returns the unit type ().
  • The value of the last expression in the function body is automatically returned, unless it ends with a semicolon (which turns it into a statement). The return keyword can be used for early returns.

2.7.2 Methods

In Rust, methods are similar to functions but are defined within impl blocks and are associated with a specific type (like a struct or enum). The first parameter of a method is usually self, &self, or &mut self, which refers to the instance the method is called on—similar to the implicit this pointer in C++.

Methods are called using dot notation: instance.method() and can be chained.

struct Point {
    x: i32,
    y: i32,
}

impl Point {
    // Method that calculates the distance from the origin
    fn magnitude(&self) -> f64 {
        // Calculate square of components, cast i32 to f64 for sqrt
        ((self.x.pow(2) + self.y.pow(2)) as f64).sqrt()
    }
}

fn main() {
    let p = Point { x: 3, y: 4 };
    println!("Distance from origin: {}", p.magnitude());
}

Key Points (Methods):

  • Methods are functions tied to a type and defined in impl blocks.
  • The first parameter is typically self, &self, or &mut self, representing the instance.
  • Methods are called using dot (.) syntax.
  • Methods without a self parameter (e.g., String::new()) are called associated functions. These are often used as constructors or for operations related to the type but not a specific instance.

2.7.3 Comparison with C

#include <stdio.h>

// Function declaration (prototype) often needed in C
int add(int a, int b);
void greet(void);

int main() {
    int sum = add(5, 3);
    printf("5 + 3 = %d\n", sum);
    greet();
    return 0;
}

// Function definition
int add(int a, int b) {
    return a + b; // Explicit return statement required
}

void greet(void) {
    printf("Hello from the greet function!\n");
    // No return statement needed for void functions
}
  • C often requires forward declarations (prototypes) if a function is called before its definition appears. Rust generally doesn’t need them within the same module.
  • C requires an explicit return statement for functions returning values. Rust allows implicit returns via the last expression.
  • C does not have a direct equivalent to methods; behavior associated with data is typically implemented using standalone functions that take a pointer to the data structure as an argument.