[Day3] Android - Kotlin笔记:高阶函式与 lambda

来理解一下lambda

以下简单介绍lambda的演进


我们一般写一个function:

    fun sayHi() {
        //doSomething
    }

在kotlin也可写作变数一样,这时fun可写成匿名函数来展现:

    val sayHi = fun() { // <-匿名函数:没有名字的function,像这个
        println("hello world")
    }

变数的型态宣告实际上长这样:

():没有传入参数,Unit:没有返回值

    val sayHi: () -> Unit = fun() {
        println("hello world")
    }

因为匿名函数没有名称,所以省去他会变这样,这就是lambda:

    val sayHi: () -> Unit = {  println("hello world")  }

没有传入值与返回值,因此型态宣告也可以省略,最简写的样子:

    val sayHi = { println("hello world") }

带入参数与返回值的lambda

理解了lambda的简单概念後,来更进一步运用

今天我们要将值以币种为前缀来显示,
以前会这样写:

    fun moneyFormat ( money: Int): String {
        return "NT.$money"
    }

了解lambda後:


    //原本变数命名方式,全部展开会像这样
    val moneyFormat: (money: Int) -> String = fun(money: Int): String { 
        return "NT.$money"
    }
    

将匿名函数省去(简易省去版)

->前面的变数会被编译器认作为函数的带入值,
而function中的最後一行则会被当作函数的返回值。

moneyFormatOmitVer更简写,
在只有一个带入参数的情况下,可以选择不命名他,
编译器会将其默认命名为it来使用,非常省时。

    val moneyFormat: (money: Int) -> String = { money -> "NT.$money" }
    
    val moneyFormatOmitVer: (money: Int) -> String = { "NT.$it" }

由於带入值及返回值都可写在fun中,
因此我们发现更简洁的写法(终极简写版)

    val moneyFormat = { money: Int -> "NT.$money" }

带入复数参数

理解了上述观念後,玩玩看带入两个参数

你以前会这样写:

    fun plus (firstNum: Int, secondNum: Int): Int {
        return firstNum + secondNum
    }

现在可以写更少字、更简易:

    //lambda
    val plus = { firstNum: Int, secondNum: Int ->
        firstNum + secondNum
    }

高阶函式

理解lambda後,高阶函式就更易懂了。

定义:带入值或返回值型别是一个函式的函式。

举例:

    fun calculate(firstNum: Int, secondNum: Int, operator: (Int, Int) -> Int): String {
        return "${operator(firstNum, secondNum)}"
    }
    
    val plus = { firstNum: Int, secondNum: Int ->
        firstNum + secondNum
    }
    
    val minus = { firstNum: Int, secondNum: Int ->
        firstNum - secondNum
    }
    

calculate就是一个将函式带入函式的高阶函式。
这时当我们执行println(calculate(1, 2, plus))时,
会得到:3
执行println(calculate(1, 2, minus))时,
会得到:-1

当然我们也能合并,把calculate简化成lambda:

    val calculate = { firstNum: Int, 
                             secondNum: Int, 
                             operator: (Int, Int) -> String ->
        "${operator(firstNum, secondNum)}"
    }

也能像这样,让他先去做某件事:

    val multiply = { firstNum: Int, secondNum: Int, doFirst: () -> Unit ->
        doFirst.invoke() //.invoke()可省略,用doFirst()也是可以的
        firstNum * secondNum
    }

    fun test () {
        multiply(1, 2, {
           Toast.makeText(context, "hello bro", Toast.LENGTH_SHORT).show()
        })
    }

参考资源:


<<:  ASP.NET MVC 从入门到放弃 (Day1) -基本语言介绍

>>:  DAY6 - 链表(二)

解决QEMU:Failed to open module: ........的问题

问题: 照着https://wiki.debian.org/QEMU 的教学 输入这两行指令没问题 ...

Day12:Select Room(选择特定房间频道)

全文同步於个人 Docusaurus Blog 本章的需求,解决首页进入前,如果有特定频道可以选择...

JavaScript 魔法入门 - 前言

前情提要 那天窗外微微透点薄光,听到门外传来了些许奇妙的声响,走到门外看到地板上掉落一张纸。 拿起了...

[DAY 27] 章节3-7: 对立的鸡群们- k-means(k平均分类演算法) (1/2)

3-7 对立的鸡群们 在飞哥的工作室也待好一阵子的小博,这天在网路上收集资料,以便帮飞哥在报告上有更...

Checkbox 与 Radio 组件-金鱼都能懂的Bootstrap5网页框架开发入门

Bootstrap已是目前全球被大量网页开发者使用的一个网页UI框架了,其特色在於使用简单,开发快速...