Loading...
Loading...

Rust Functions: From Basics to Advanced

Functions in Rust are reusable blocks of code that perform specific tasks. They are declared with the fn keyword, can accept parameters, return values, and enforce strict type checking at compile time. Rust functions support expression-based returns, generics, and advanced features like closures and higher-order functions.

1. Defining and Calling Functions

Basic function syntax in Rust requires explicit type annotations for parameters and return values. Functions are defined using the fn keyword and called by their name followed by parentheses.

// Basic function definition
fn greet(name: &str) {  // &str parameter type
    println!("Hello, {}!", name);  // No return value
}

// Function with return value
fn add(a: i32, b: i32) -> i32 {  // -> specifies return type
    a + b  // Expression without semicolon = return value
}

// Calling functions
fn main() {
    greet("Alice");  // Call with string literal
    let sum = add(5, 3);  // Capture return value
    println!("Sum: {}", sum);
}

Function Quiz

Why doesn't the add function use a return keyword?

  • Rust doesn't support return statements
  • The last expression in a block is automatically returned
  • Only primitive types can be returned without return

Key Points: Rust functions use snake_case naming. The return type must be specified after ->. Expressions without semicolons are returned implicitly, while return is used for early returns.

2. Parameters and Arguments

Function parameters in Rust can be immutable or mutable references, and the compiler enforces proper borrowing rules. Parameters must always have explicit types.

// Immutable parameter (borrows the String)
fn print_length(s: &String) {
    println!("Length: {}", s.len());  // Can read but not modify
}

// Mutable parameter (borrows mutably)
fn append_world(s: &mut String) {
    s.push_str(" world!");  // Can modify the string
}

// Multiple parameters with different types
fn calculate(x: f64, y: f64, operation: char) -> f64 {
    match operation {
        '+' => x + y,  // Pattern matching on operation
        '-' => x - y,
        _ => panic!("Unknown operation"),  // Crash on invalid input
    }
}

Parameters Quiz

What's the difference between &String and &mut String parameters?

  • They're identical in behavior
  • The mutable reference allows modifying the value
  • Only &mut works with strings

Parameter Rules: Rust enforces one mutable reference OR multiple immutable references. Function signatures document whether parameters are borrowed or owned. Complex types should generally be passed by reference.

3. Returning Values from Functions

Return values in Rust can be explicit using the return keyword or implicit via expressions. Functions can return multiple values using tuples, or optional values using Option/Result.

// Early return with explicit return statement
fn early_return(x: i32) -> i32 {
    if x < 0 {
        return 0;  // Early exit with return
    }
    x * 2  // Implicit return (no semicolon)
}

// Returning multiple values with a tuple
fn stats(numbers: &[i32]) -> (f64, i32) {
    let sum: i32 = numbers.iter().sum();
    let mean = sum as f64 / numbers.len() as f64;
    (mean, sum)  // Return tuple (parentheses required)
}

// Returning Option for fallible operations
fn divide(a: f64, b: f64) -> Option<f64> {
    if b == 0.0 {
        None  // Indicate failure
    } else {
        Some(a / b)  // Wrap success value
    }
}

Return Quiz

What does this function return if numbers = [1, 2, 3]?

fn mystery(numbers: &[i32]) -> i32 {
    numbers.iter().fold(0, |acc, &x| acc + x)
}
  • [1, 2, 3]
  • 6
  • (6, 3)

Return Best Practices: Prefer implicit returns for simple functions. Use Option when operations might fail. Return tuples for multiple values, but consider structs for complex cases.

4. Function Pointers and Higher-Order Functions

Function pointers allow treating functions as values. Higher-order functions accept or return other functions, enabling powerful abstraction patterns.

// Type alias for function pointer
type MathOp = fn(i32, i32) -> i32;

// Higher-order function accepting a function pointer
fn apply_operation(a: i32, b: i32, op: MathOp) -> i32 {
    op(a, b)  // Call the passed function
}

// Concrete operation functions
fn add(x: i32, y: i32) -> i32 { x + y }
fn multiply(x: i32, y: i32) -> i32 { x * y }

fn main() {
    // Pass add function as argument
    let result = apply_operation(3, 4, add);
    println!("Result: {}", result);  // 7
    
    // Pass multiply function
    let product = apply_operation(3, 4, multiply);
    println!("Product: {}", product);  // 12
}

Function Pointers Quiz

What is the type of add in this code?

  • i32
  • fn(i32, i32) -> i32
  • MathOp

Function Pointer Notes: Function pointers differ from closures (which capture environment). The type syntax explicitly shows parameter and return types. Useful for strategy patterns or callbacks.

5. Generic Functions

Generic functions work with multiple types while maintaining compile-time type safety. Type parameters are declared in angle brackets and can have trait bounds.

// Generic function with trait bound
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    
    for item in list {
        if item > largest {  // Requires PartialOrd
            largest = item;
        }
    }
    
    largest
}

// Multiple generic type parameters
fn pair<T, U>(first: T, second: U) -> (T, U) {
    (first, second)  // Return tuple of generic types
}

fn main() {
    let numbers = vec![34, 50, 25, 100, 65];
    println!("Largest: {}", largest(&numbers));
    
    let mixed = pair("hello", 42);  // Different types
    println!("Pair: {:?}", mixed);
}

Generics Quiz

What does T: PartialOrd mean in the generic constraint?

  • T must be a pointer
  • T must support comparison operations
  • T must be a numeric type

Generic Tips: Use trait bounds to specify required functionality. Compiler generates specialized versions for each used type. Generics enable code reuse without runtime costs.

0 Interaction
0 Views
Views
0 Likes
×
×
×
🍪 CookieConsent@Ptutorials:~

Welcome to Ptutorials

$ Allow cookies on this site ? (y/n)

top-home