Functions

Named functions

  • Named functions are declared with the keyword fn
  • When using arguments, you must declare data types.
  • By default, functions return empty tuple/ (). If you want to return a value, the return type must be specified after ->

i. Hello world

fn main() {
    println!("Hello, world!");
}

ii. Passing arguments

fn print_sum(a: i8, b: i8) {
    println!("sum is: {}", a + b);
}

iii. Returning values

// 01. Without the return keyword. Only last expression returns.
fn plus_one(a: i32) -> i32 {
    a + 1
    // There is no ending ; in the above line. It means this is an expression which equals to `return a+1;`
}

// 02. With the return keyword.
fn plus_two(a: i32) -> i32 {
    return a + 2; // Returns a+2. But, this's a bad practice.
    // Should use only on conditional returns, except in the last expression
}

iv. Function pointers, Usage as a Data Type

// 01. Without type declarations
let b = plus_one;
let c = b(5); //6

// 02. With type declarations
let b: fn(i32) -> i32 = plus_one;
let c = b(5); //6

Closures

  • Also known as anonymous functions or lambda functions.
  • The data types of arguments and returns are optional.

Example with a named function, before using closures.

fn main() {
  let x = 2;
  println!("{}", get_square_value(x));
}

fn get_square_value(x: i32) -> i32 {
    x * x
}

i. With optional type declarations of input and return types

fn main() {
    let x = 2;
    let square = |x: i32| -> i32 { // Input parameters are passed inside | | and expression body is wrapped within { }
        x * x 
    };
    println!("{}", square(x));
}

ii. Without type declarations of input and return types

fn main() {
    let x = 2;
    let square = |x| x * x; // { } are optional for single-lined closures
    println!("{}", square(x));
}