Kotlin學習日記(十)Kotlin函數語言程式設計相關知識
阿新 • • 發佈:2019-02-07
尾遞迴函式
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的偏函式