Rust - Functions


A function in Rust starts with fn. For example:

fn main() {
    // Body
}

main() is the most important function and is where the Rust program starts.

Rust does not care where a function is defined, it just needs to be defined. For example:

fn main() {
    other_function();
}

fn other_function() {
    println!("This function is declared after main. It could have been declared before main.");
}

Function Pointers

You can pass functions as parameters to functions as well! The fn type is a function pointer.

Function pointers implement all three closure traits Fn, FnMut, and FnOnce).

fn double(x: u32) -> u32 {
    x * 2
}

fn do_twice(f: fn(u32) -> u32, arg: u32) -> u32 {
    f(arg) * f(arg)
}

fn main() {
    assert_eq!(
        16, 
        do_twice(double, 2)
    )
}

Paramaters

Type annotations for parameters are required in Rust.

fn main() {
    other_function(12, 'a');
}

fn other_function(x: i32, c: char) {
    println!("The value of x is: {}", x);
    println!("The value of c is: {}", c);
}

Return Values

Rust requires you to declare a return type for a function if it returns something.

The last line in a function is returned implicitly as long as it is an expression (no semi-colon). A return statement can be used to return prior to the last line.

fn three() -> i32 {
    3 // Notice the lack of a semi-colon. Expressions return something, statements do not.
}

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

fn minus_one(x: i32) -> i32 {
    // Because we are explicitly using "return" we can either make this
    // a statement or an expression.
    return x - 1; 
}

fn no_return(x: i32) {
    println!("{}, x");
}

fn main() {
    let x = three();
    println!("x is: {}", x);

    let x = plus_one(x);
    println!("x is now: {}", x);

    let x = minus_one(x);
    println!("x is finally: {}", x);
}