Lambdas in Kotlin

Using lambdas in Kotlin.

// Lambdas have to be inside curly braces and can be used as variables. Can be called directly through the 'run' library function

fun main() {
    run { println("I'm in a lambda") } // run function at work

    val employees = listOf(KotlinEmployee("John", "Smith", 2012), KotlinEmployee("Jane", "Wilson", 2015), KotlinEmployee("Mary", "Johnson", 2010), KotlinEmployee("Mike", "Jones",2002))
    println(employees.minBy { e -> e.startYear }) // minBy expects lambda. Each element is iterated through as e and the startYear compared. Returns employee with the earliest starting year
    println(employees.minBy { it.startYear }) // As there is only one argument we can use 'it'
    println(employees.minBy (KotlinEmployee::startYear)) // This is a member reference, and can be used instead of a lambda expression...
    // ...when only accessing a property or when it calls a top-level function that doesn't take any parameters (must be inside parentheses)
    run (::topLevel) // Calling top-level function member variable. No arguments allowed.
    //Lambdas can access local variables as long as they are declared before it. When you use a lambda within a function it can also access the function parameters:
    var num = 10 // Unlike Java (final local variables only) this can be accessed despite being mutable
    run {
        num += 15
        println(num)
    }

    useParameter(employees, 53) // Lambda accessing function parameter
}

data class KotlinEmployee(val firstName: String, val lastName: String, val startYear: Int) { // Data class overrides our toString for a legible output

}

fun topLevel() = println("I'm a function")

fun useParameter (employees: List<KotlinEmployee>, num: Int) {
    employees.forEach {
        println(it.firstName)
        println(num)
//        num++ // Cannot change function parameters as they are val. Can only access them
    }
}