1. 程式人生 > >Kotlin學習日記(十)Kotlin函數語言程式設計相關知識

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<String>) {
    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<String>) {
    val consoleLogWithTag = (::log.curried())("main")(System.out)
    consoleLogWithTag("HelloAgain Again.")
    consoleLogWithTag("HelloAgain Again.")
    consoleLogWithTag("HelloAgain Again.")
    consoleLogWithTag("HelloAgain Again.")

}

consoleLogWithTag就可以說是log的偏函式