匿名函數
在前面的章節我們認識了函數,不過我們寫的函數都有名字。接下來我們會看到一種“沒有名字”的函數,我們把它稱之為匿名函數或是lambda函數。我們先來看看一個lambda函數的簡單例子
lambda類型
lambda函數跟一般的函數一樣,有傳入0-多個東西然後傳出1個東西的功能,那我們來看看lambda函數的型態要怎麼表示:
在這個範例裡面,我們把前面的lambda函數拆開來,並且設定給一個變數。我們知道變數只能裝符合型態的東西,所以我們必須了解lambda函數的型態是什麼。
() -> String
lambda函數的型態我們會寫成這樣,從左到右依序是“(參數型態們)”、“ -> ”、“回傳型態”。用這樣的定義我們來看看上面的範例“() -> String”,指的就是這個lambda函數沒有參數,最後會回傳一個字串的意思。
隱式返回
在上面的lambda函數裡面有沒有發現雖然我們說是函數,但是最後並沒有return呢?其實在大多數情況下lambda函數並不需要使用return來回傳東西,lambda函數會回傳“最後一句話的結果”。
而為什麼return寫在這裡反而會錯呢?是因為這樣編譯器沒辦法判斷我們要返回的是哪一層的函數。所以假如我們真的有必要寫道return的話,我們可以幫lambda函數上“標籤”:
利用標籤來讓編譯器知道我們要返回的是什麼函數,這樣編譯器就不會搞混了,而我們在後面會討論到有時候lambda函數會有“預設標籤”這一個特性。
參數
lambda函數既然也是函數,那就會有要傳入東西的需求,接下來我們就來看看下面的範例:
lambda函數的參數我們會寫在大括號的後面,然後再接一個箭頭(->),而且傳入引數的方式也跟我們在呼叫一般函數的方式一樣。同樣的如果我們想要定義多個參數的話,也是一樣的方法:
我們傳入了多個參數型態,這些我們全部寫進“( )”裡面並用“,”隔開,參數名字也是全部寫在箭頭(->)前面,並用“,”隔開
it關鍵字
lambda函數有一個特別的關鍵字it,他只會出現在只有一個參數的lambda函數裡面。我們使用ex. 6-2-1的程式碼來示範
我們看到我們省略了明確的參數名字還有箭頭(->),並且使用“it”來代替參數,這個是在只有一個一個參數的lambda函數裡面特別可以使用的。
把lambda函數當成參數
我們也可以把lambda函數當成另一個函數的參數,這樣可以增加方法的彈性:
簡略語法
如果lambda函數是所有參數的最後一個的話,我們可以把lambda寫在“( )”後面:
因為有這樣的簡略語法,通常我們在定義函數,只有一個參數是lambda函數的時候,我們就會把lambda函數放在參數的最後一個,並在呼叫的時候使用簡略語法。這樣字寫起來比較簡單易讀。
函數內聯
接下來我們來介紹內聯“inline”關鍵字,在Kotlin裡面我們會大量的使用lambda函數,這是程式語言提供的優勢,可是當程式碼編譯在JVM上的時候每一個lambda函數都會變成物件實例,這樣在做大量的資料處理的時候會對我們的效能產生很大的負擔。為了避免這樣的狀況我們可以使用“inline”關鍵字,使用inline關鍵字後,呼叫函數的時候並不會產生lambda函數的物件實例,而是會把函數的內容“貼上”一份在呼叫函數的地方,這樣可以增加效能。
不過內聯函數並不是萬用解,在某些時候並不能使用內聯函數,而通常這種時候編譯器也會提醒我們,比如:遞迴函數
函數參照
lambda函數很方便,可是如果我們想要使用現有的函數當作引數傳入的話要怎麼辦呢?
這邊我們看到了新的運算子“::”,他可以把一個有名字的函數轉換成一個引數,讓我們可以把函數傳入函數裡面,只要是函數的型態跟要傳入的lambda函數一樣的時候都可以使用函數參照來傳入具名的函數。
使用lambda函數作為回傳值
lambda函數可以被當作參數,當然也可以當作回傳值,而且當我們看到下面的範例,我們可以發現lambda函數一些有趣的特性:
我們發現在執行的時候,回傳的lambda函數每被呼叫一次,同學的座號就會被加1。為什麼會這樣呢?其實當我們在使用lambda函數的時候,我們可以把每一次“實體化的lambda函數”當成是一個自己的小世界,在裡面取用的變數他的結果會被保留下來,所以就會造成這樣的結果。
typealias
寫了這麼多lambda函數,有時候我們會覺得要寫這種“(......) -> ......”的型態我們會覺得很醜或是有時候我們看著看著就搞錯這個lambda函數是什麼作用。這個時候我們就可以使用“typealias”關鍵字來幫lambda函數命名,以上一個範例來說,我們可以改成這樣:
練習
定義一個函數可以自行決定學號的輸出格式並在main函數裡呼叫兩次,分別讓他輸出
“TIP101-__”
“400420__S”
Last updated