Kotlin學習筆記(14)- lambda

系列文章全部為本人的學習筆記弟跑,若有任何不妥之處廊蜒,隨時歡迎拍磚指正添寺。如果你覺得我的文章對你有用胯盯,歡迎關注我,我們一起學習進步计露!
Kotlin學習筆記(1)- 環(huán)境配置
Kotlin學習筆記(2)- 空安全
Kotlin學習筆記(3)- 語法
Kotlin學習筆記(4)- 流程控制
Kotlin學習筆記(5)- 類
Kotlin學習筆記(6)- 屬性
Kotlin學習筆記(7)- 接口
Kotlin學習筆記(8)- 擴展
Kotlin學習筆記(8)- 擴展(續(xù))
Kotlin學習筆記(9)- 數據類
Kotlin學習筆記(10)- 泛型
Kotlin學習筆記(11)- 內部類和嵌套類
Kotlin學習筆記(12)- 委托
Kotlin學習筆記(13)- 函數式編程
Kotlin學習筆記(14)- lambda

在上一篇《Kotlin學習筆記(13)- 函數式編程》的最后我提到lambda為函數式編程提供了更多更好的實現(xiàn)博脑,如果你還不太了解什么是函數式編程,那么可以看看我的上一篇文章票罐。那么我們首先來看看什么是lambda叉趣,在百度百科上是這么說的:

“Lambda 表達式”(lambda expression)是一個匿名函數,Lambda表達式基于數學中的λ演算得名该押,直接對應于其中的lambda抽象(lambda abstraction)疗杉,是一個匿名函數,即沒有函數名的函數蚕礼。Lambda表達式可以表示閉包(注意和數學傳統(tǒng)意義上的不同)烟具。

一、Lambda的定義

看上面的說法有點抽象奠蹬,有點不明所以朝聋,我們先來看一個栗子

class Num {
    fun logic(a: Int, b: Int, calc: (Int, Int) -> Int){
        println("calc : ${calc(a,b)}")
    }
}

fun main(args : Array<String>){
    val num = Num()
    num.logic(1, 2, {x,y -> x+y})
}

// 輸出
calc : 3

這個栗子和上一篇文章很像,只是在調用的時候改成了Lambda方式:num.logic(1, 2, {x,y -> x+y})囤躁,其中{x,y -> x+y}就是我們今天要講的Lambda表達式冀痕,它的完整格式應該是這樣

{ x: Int, y: Int -> x + y }

寫成java代碼是這個樣子:

public int sum(int x, int y){
    return x+y;
}

可以很明顯看出有幾個規(guī)則:

  1. 參數寫在->左邊,格式與普通函數的參數格式一樣狸演,多個參數用逗號,分割
  2. 參數的類型可選言蛇,可忽略,編輯器會根據上下文推斷(這就和普通函數不一樣了吧宵距,有種“我知道你懂得猜极,所以就不寫了”的感覺有木有,知己的感覺啊……)
  3. 函數體跟在->右邊
  4. Lambda表達式總是被大括號{}包圍著

二消玄、Lambda中的一些約定

  1. 如果 Kotlin 可以自己計算出簽名跟伏,它允許我們不聲明唯一的參數,并且將隱含地為我們聲明其名稱為 it翩瓜。其實通常情況下它都可以自己計算出簽名受扳,也就是說,如果函數字面值只有一個參數兔跌, 那么它的聲明可以省略(連同 ->)板熊,其名稱是 it

    fun oneParams(one : (Int) -> Int){
        println("oneParams : ${one(5)}")
    }
    
    fun main(args : Array<String>){
        val num = Num()
        num.oneParams({it * 2})
    }
    
    // 輸出
    oneParams : 10
    

    說到省略,其實還有一種情況可以省略->项钮,大家應該也能想到,就是無參函數蕊蝗。

    fun empty(emptyM : () -> Unit){
        emptyM()
    }
    
    fun main(args : Array<String>){
        val num = Num()
        num.empty({println("empty method")})
    }
    
    // 輸出
    empty method
    
  2. 如果Lambda中的某個參數沒有用到,可以用下劃線_代替赖舟,也就是說蓬戚,省了好多請名字的腦細胞有木有!這個特性從1.1開始可以使用宾抓,現(xiàn)在你看到的時候應該已經不止1.1了吧子漩,所以這個限制看看就好~

    fun unusedParams(unused : (Int,Int) -> Int){
        println("unusedParams : ${unused(5,10)}")
    }
    
    fun main(args : Array<String>){
        val num = Num()
        num.unusedParams { _, used -> used * 2 }
    }
    
    // 輸出
    unusedParams : 20
    
  3. 如果函數的最后一個參數是一個函數,那么我們在用Lambda表達最后一個函數參數的時候石洗,可以把它放在括號()外面幢泼,所以下面的寫法是等價的。

    class Num {
        fun logic(a: Int, b: Int, calc: (Int, Int) -> Int){
            println("calc : ${calc(a,b)}")
        }
        fun sum(a: Int, b: Int) = a + b
    }
    
    fun main(args : Array<String>){
        val num = Num()
        // 寫法1
        num.logic(1, 2, {x : Int,y : Int -> x+y})
        // 寫法2
        num.logic(1, 2){x : Int,y : Int -> x+y}
        // 寫法3
        num.logic(1, 2){x,y -> x+y}
    }
    

    那么這么寫有什么好處呢讲衫?難道只是位置變了一下缕棵?當然不是,不要忘記涉兽,Lambda的->后面是方法體挥吵,也就是很多時候不是想栗子中這樣只有一行,如果有多行的話花椭,體會一下他們的區(qū)別:

    num.logic(1, 2, {x,y ->
        println("extra line")
        x+y
    })
    
    num.logic(1, 2){x,y ->
        println("extra line")
        x+y
    }
    

    是不是感覺下面的寫法要優(yōu)雅很多忽匈,也明確很多?

  4. 其實在上面一點應該已經能看出矿辽,如果有需要的話丹允,Lambda會隱式的返回最后一個表達式的值,就像上面的最后一行x+y袋倔。當然雕蔽,我們也可以顯示的表達返回值,下面的寫法還是一樣的:

    // 寫法1
    num.unusedParams { _, used ->
        println("print first")
        return@unusedParams used * 2
    }
    
    // 寫法2
    num.unusedParams { _, used ->
        println("print first")
        used * 2
    }
    

三宾娜、匿名函數

看了這么多批狐,我們發(fā)現(xiàn)一個問題,Lambda的返回類型全是自動推斷的前塔,雖然很人性化嚣艇,但是有時候我們就是想自己指定類型怎么辦?當然是有辦法的华弓,那就是匿名函數食零。

fun(x:Int, y:Int):Int{return x+y}

匿名函數看起來非常像一個常規(guī)函數聲明,除了其名稱省略了寂屏。其函數體可以是表達式(如上所示)或代碼塊贰谣。由于這已經不算正經的Lambda娜搂,所以它不需要被大括號{}包裹,也不能像Lambda一樣寫在括號()外吱抚,而調用也是直接調用百宇。

num.logic(1, 2, fun(x:Int, y:Int):Int{return x+y})

四、閉包

Lambda 表達式或者匿名函數(以及局部函數對象表達式) 可以訪問其 閉包 秘豹,即在外部作用域中聲明的變量携御。 與 Java 不同的是可以修改閉包中捕獲的變量:

var sum = 0
ints.filter { it > 0 }.forEach {
    sum += it
}
print(sum)

五、小結

其實沒什么小結憋肖,關于更多的函數式的高級應用因痛、復雜應用婚苹,個人也正在學習岸更,大家互相交流。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末膊升,一起剝皮案震驚了整個濱河市怎炊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌廓译,老刑警劉巖评肆,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異非区,居然都是意外死亡瓜挽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門征绸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來久橙,“玉大人,你說我怎么就攤上這事管怠∠裕” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵渤弛,是天一觀的道長祝拯。 經常有香客問我,道長她肯,這世上最難降的妖魔是什么佳头? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮晴氨,結果婚禮上畜晰,老公的妹妹穿的比我還像新娘。我一直安慰自己瑞筐,他們只是感情好凄鼻,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布腊瑟。 她就那樣靜靜地躺著,像睡著了一般块蚌。 火紅的嫁衣襯著肌膚如雪闰非。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天峭范,我揣著相機與錄音财松,去河邊找鬼。 笑死纱控,一個胖子當著我的面吹牛辆毡,可吹牛的內容都是我干的。 我是一名探鬼主播甜害,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舶掖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了尔店?” 一聲冷哼從身側響起眨攘,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嚣州,沒想到半個月后鲫售,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡该肴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年情竹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匀哄。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡秦效,死狀恐怖,靈堂內的尸體忽然破棺而出拱雏,到底是詐尸還是另有隱情棉安,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布铸抑,位于F島的核電站贡耽,受9級特大地震影響,放射性物質發(fā)生泄漏鹊汛。R本人自食惡果不足惜蒲赂,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刁憋。 院中可真熱鬧滥嘴,春花似錦、人聲如沸至耻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至走触,卻和暖如春晦譬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背互广。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工敛腌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惫皱。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓像樊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親旅敷。 傳聞我的和親對象是個殘疾皇子生棍,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內容