lambda表达式

高阶函数

高阶函数就是接受一个函数为参数,或者返回一个函数。

fun caculate(a: Int, b: Int, calc: (a: Int, b: Int) -> Int) {
    println(calc(a, b))
}

fun main() {
    caculate(1, 2){ a, b -> a + b }
    caculate(1, 2){ a, b -> a - b }
    caculate(1, 2){ a, b -> a * b }
    caculate(1, 2){ a, b -> a / b }
}

lambda表达式的返回值

在默认情况下,lambda表达式的最后一条语句的返回值会作为该lambda表达式的返回值,我们可以通过全限定的return语法来显示的指定返回值。

fun main() {
    var strings = arrayOf("hell", "hello", "a", "world")

    strings.filter { it.length > 3 }

    strings.filter { return@filter it.length > 3 }
}

匿名函数

匿名函数的方法体是一个表达式时,可以省略返回值,编译器能够推导出来。

匿名函数的方法体是一个代码块时,不能省略返回值,编译器能够推导出来。

匿名函数的参数类型有时也能被省略(如果能从上下文中推导的话)。

package com.morris.kotlin.lambda

fun main() {
    fun(a: Int, b: Int) = a + b

    fun(a: Int, b: Int): Int {
        return a + b
    }

    var strings = arrayOf("hell", "hello", "a", "world")

    strings.filter(fun(it) = it.length > 3).forEach(fun(it) = println(it))
}

闭包

lambda表达式或者匿名函数内部能修改外部的变量。

fun main() {

    var sum = 0

    var strings = arrayOf("hell", "hello", "a", "world")

    strings.forEach { sum += it.length }

    println(sum)
}

带接收者的函数字面值

kotlin提供了这样一种功能:可以通过指定的接收者对象来调用一个函数字面值,在函数字面值内部,你可以调用接收者内部的方法(this)而无需使用任何额外的修饰符。

var sum: Int.(Int)->Int = { this + it }
println(1.sum(10))

匿名函数也可以指定函数字面值的接收者类型,这样我们就可以先去声明一个带有接收者的函数型变量,然后再去使用它。

var sum2 = fun Int.(other: Int): Int = this + other
println(1.sum2(10))

带有接收者类型的函数的非字面值可以作为参数进行传递,前提是所需要接收函数的地方有一个接收者类型的参数,反之亦然。

比如说:类型String.(Int)->Boolean与(String, Int)->Boolean等价。

val myEquals: String.(Int) -> Boolean = { this.toIntOrNull() == it }

println("456".myEquals(456)) // true

fun myTest(op: (String, Int) -> Boolean, a: String, b: Int, c: Boolean) = op(a, b) == c

myTest(myEquals, "123", 123, true)