fn main() {
    println!("Hello, world!");
    example_function(1, 4);     // can be delared before or after function that uses it
    println!("From Return function: {}", with_return_plus_one(18));
}

// fn is the keyword for functions
fn example_function (x:i8, y:u16) {
    // type must be delared cannot be inferred
    // name of parameter/argument is in the brakets seperated by commas
    // {} show scope of function

    // can be used directly form pram delaration
    println!("Look anthoer Function {} {y}", x);
    let a = {
        let b = 3;
        b + 1
    };
    println!("The value of a is: {a}");


}

// Statements do not return a value
// Function def is a statement
// Calling a function is not a statement
// let is a statement, and cannot assign anything nor does it return anything unlike in C and Ruby
// let x = (let y = 6);
// STATEMENTS END WITH ;


// Expressions evalulate and may return a non-unit value
// let y = 6 is an expression that evalulates to 6, then writes to memory under the variable y
// calling a function is an expression, math, and calling a macro are all expressions
// adding a new scope block using {} is an expression
//  ex let y = { // value bound to y in the statment let y is 6
//      let x = 5;
//      x + 1
//     }
// macros are statements

//  EXPRESSIONS DO NOT END WITH ;
// if you add a ; to the end of a statment it will turn into a statement and not return anything
// unless it is a return keyword


fn with_return_plus_one (c: i16) -> i16 {
    // return 8; // can return early with return keyword
    c + 1 // also allowed an a normal function
    // c + 1; this is not an expression and will not return a value
}

// if you want to return a non-unit must decalre type after -> keyword
// return value is the same as the final value is the same as the last line/expression in the function
// can return early with the return keyword plus a value but it is implied by default
// return type must match unit != i16 and thereforw will cause an error

fn five () -> i32 {
    5 // this is an expression
}

// also perfectally valid
// can assign values from a expression/function return

fn assign_five_fn () {
    let d = five();
}

// comments annotate the code below it
// no multiline comments