Rust :: Functions

Functions

Statements and Expressions

// Statements end in ;
// Do not return value, or return ()
let x = 5;
x;

// Expressions do not end in ;
// Return value
// {} blocks are expressions
let z = {
    2
}

Functions

// snake_case
// no restriction on order of fn definitions
fn name(x: i32, y: i64) -> bool {
    statements;
    expression
}

// when no return specified, it's returning ()
fn name() { ... }

// `!` is actual no return allowed
fn last_fn() -> ! { ... }

// statement: perform action, do not reutn a value
// expression: evaluate to result a value, no ; at end
{
    variable
} // variable will drop after {}

// calling a function/macro is an expression
let y = {
    let x = 3;
    x + 1 // remember no ;
};

// return value
// return with expression
fn five() -> i32 {
    5
}

// associated functions: defined on a type
SomeStruct::init(x: 0.0, y: 0.0);
// methods: called on an instance of a type
rectu.area();

// function call or method call with genetic type
// turbofish, need ::<...> between method name and ()
Vec::<i32>::with_capacity(1000)     // need ::< or drop the ::<i32> and let compiler infer
let ramp = (0 .. n).collect::<Vec<i32>>();
let ramp: Vec<i32> = (0 .. n).collect();    // reads better

let four = "4".parse::<u32>();

Closure

let closure = |val: i32| -> i32 { val + 1};
let closreu = || 1; // return 1
let clos = |num| {
    println!("doing something");
    // more code
}; 
closure();  // similar way to call closure

// |_|
some.map(|_| println!("we need to take para, but we dont care"));

fn() -> SomeType    // this is a function only
Fn() -> SomeType    // this is Fn trait, function and closures

// Redundant_closure
// if `foo(_)` is a plain fn that takes the exact arg type of x
//bad
xs.map(|x| foo(x));
// good
xs.map(foo);

Function Pointers

// passing function as a parameter
// using trait
fn map<T, U, F>(input: Vec<U>, mut function: F) -> Vec<T> 
where F: FnMut(U) -> T,
{
    let mut output: Vec<T> = vec![];
    for t in input {
        output.push(function(t));
    }
    output
}

// passing fn as a parameter
// dont have to deal with lifetime
// but cannot accept closure that capture env
fn matcher<T, S>(matcher: fn(T) -> bool, sub: S) -> Matcher<T> {}

// function-type field in struct
struct Matcher<T> {
    func: fn(T) -> bool,
    sub: String,
}

// to call a function-type field
let s = Matcher::<T>::new();
(s.func)(some_t)