Functions

Rust by example - Functions

fn foo(x: i32, unit_label: char) -> i32 {
    let y = {
        let z = 3;
        x + z // Expression at the end of a block - no semi-colon
    };

    println!("The value of y is: {y}{unit_label}");
    y // Returns y - no semi-colon
}

fn main() {
    println!("{}", foo(1, 'm'));
}

The unit type () (void in some languages) is the default return type when no type is given for a function. It could be omitted: fn log(message: &str) { ... }

Generic functions

fn generic<T>(_t: T) {
    println!("In `generic`");
}

// Explicitly specified type parameter `char` to `generic()`.
// Note the turbofish notation ::<>

fn main() {
    generic::<char>('a');
}
use std::fmt::Display;

fn generic<T: ?Sized + Display>(t: &T) {
    // By default, generic functions will work only on types that have a
    // known size at compile time. Use `?Sized` to relax that rule.
    // `t` must be some kind of (smart) pointer: &, `Rc`, `Box`...
    println!("{}", t);
}

fn main() {
    let s = String::from("hello");
    generic(&s[..]);
}

Function pointers

fn add_one(x: i32) -> i32 {
    x + 1
}

fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
    // function pointer
    f(arg) + f(arg)
}

fn main() {
    println!("{}", do_twice(add_one, 1));
}

Diverging functions

Diverging functions never return.

fn foo() -> ! {
    // ! is the Never type
    panic!("This call never returns.");
}

fn main() {
    println!("Will panic");
    foo();
}