Kotlin学习日记(十)Kotlin函数式编程相关知识

尾递归函数

kotlin 支持函数式编程的尾递归。这个允许一些算法可以通过循环而不是递归解决问题,从而避免了栈溢出。

  • 当函数被标记为 tailrec 时,编译器会优化递归,并用高效迅速的循环代替它。
  • 一种特殊的递归
  • 调用自身后无其他操作
  • 是进行了优化的循环 
tailrec fun findListNode(head: ListNode?, value: Int): ListNode?{
    head?: return  null
    if(head.value == value) return head
    return findListNode(head.next, value)
}

在递归调用代码后面是不允许有其它代码的,并且也不可以在 try/catch/finall 块中进行使用。当前的尾递归只在 JVM 的后端中可以用。

闭包

持有函数运行的状态 
函数内部可以定义函数 
函数内部也可以定义类

Lambda 表达式或者匿名函数,以及局部函数和对象表达式(object declarations)可以访问其 闭包 ,即在外部作用域中声明的变量。 与 Java 不同的是可以修改闭包中捕获的变量:

    fun sumGTZero(c: Iterable<Int>): Int {
        var sum = 0
        c.filter { it > 0 }.forEach {
            sum += it
        }
        return sum
    }

val list = listOf(1, 2, 3, 4, 5)
sumGTZero(list) // 输出 15

我们再使用闭包来写一个使用Java中的Thread接口的例子:

    fun closureDemo() {
        Thread({
            for (i in 1..10) {
                println("I = $i")
                Thread.sleep(1000)
            }

        }).start()

        Thread({
            for (j in 10..20) {
                println("J = $j")
                Thread.sleep(2000)
            }
            Thread.sleep(1000)
        }).start()
    }

一个输出:

I = 1
J = 10
I = 2
I = 3
...
J = 20

科理化

由多参函数变换为多个单个参数函数的过程。

fun log(tag: String, target: OutputStream, message: Any?){
    target.write("[$tag] $message\n".toByteArray())
}

//fun log(tag: String)
//    = fun(target: OutputStream)
//    = fun(message: Any?)
//    = target.write("[$tag] $message\n".toByteArray())

fun main(args: Array) {
    log("benny", System.out, "HelloWorld")
//    log("benny")(System.out)("HelloWorld Again.")
    ::log.curried()("benny")(System.out)("HelloWorld Again.")
}

以上是两种科理化的方式。

实际上还有反科理化,了解就行。

偏函数

有时在函数传入是往往是有个值是固定的,把这个值固定,剩下的就可以称之为偏函数

fun log(tag: String, target: OutputStream, message: Any?){
    target.write("[$tag] $message\n".toByteArray())
}

fun main(args: Array) {
    val consoleLogWithTag = (::log.curried())("main")(System.out)
    consoleLogWithTag("HelloAgain Again.")
    consoleLogWithTag("HelloAgain Again.")
    consoleLogWithTag("HelloAgain Again.")
    consoleLogWithTag("HelloAgain Again.")

}

consoleLogWithTag就可以说是log的偏函数

你可能感兴趣的:(Kotlin开发)