美文网首页
函数和Lambda表达式(一)

函数和Lambda表达式(一)

作者: 凌寒天下独自舞 | 来源:发表于2018-09-27 17:11 被阅读0次

函数入门

函数的定义和调用

函数的定义语法如下:

fun 函数名(形参列表):返回值类型{
//函数体
}

kotlin声明函数必须使用fun关键字

函数的返回值可以是kotlin所允许的任何数据类型,如果声明了函数的返回值类型,则函数体必须有一条有效的return语句,该语句返回了一个变量或者表达式,如果没有返回值则有如下2种声明方式:

  1. 省略“:返回值类型”部分
  2. 使用“:Unit”指定返回Unit代表没有返回值,相当于java中的void

函数的形参列表用于定义该函数可以接受的参数,形参列表由多组“形参名:形参类型”组合而成,中间以逗号隔开。


fun max(x: Int, y: Int): Int {
    val z = if (x > y) x else y
    return z
}

fun sayHi(name: String): String {
    return "${name} ,你好!"
}

fun foo() {
    println("执行foo()函数")
}

fun sayHello(name: String): Unit {
    print("${name},hello!")

}

fun main(args: Array<String>) {
    var a = 6
    var b = 9
    println("最大值是: ${max(a, b)}")

    print(sayHi("xq"))

    foo()

    sayHello("sq")
}

递归函数

在一个函数体内调用它自身,被称为函数的递归。

//递归函数
fun fn(n: Int): Int {
    when (n) {
        0 -> return 1
        1 -> return 4
        else -> return 2 * fn(n - 1) + fn(n - 2)
    }
}

fun main(args: Array<String>) {
    
    println("fn(10)的结果是${fn(10)}")

}

单表达式函数

在某些情况下,函数只返回单个表达式,此时可以省略花括号并在等号后指定函数体即可,这种方式被称为单表达式函数。对于单表达式函数而言,编译器可以推导出函数的返回值类型,因此可以省略不写。


//单表达式函数
fun area(x: Double, y: Double): Double = x + y

fun product(x: Double, y: Double) = x * y

fun main(args: Array<String>) {

    println("1.2 + 2.5 = ${area(1.2, 2.5)}")
    println("1.2 * 2.5 = ${product(1.2, 2.5)}")
}

函数的形参

命名参数

kotlin函数的参数名不是无意义的,kotlin允许调用函数时通过名字来传入参数值。
注意在调用函数时混合使用命名参数和位置参数时,那么命名参数必须位于位置参数的后面。


//函数的形参
//命名函数
fun girth(width: Double, height: Double): Double {
    println("width: ${width},height: ${height}")
    return 2 * (width + height)
}
fun main(args: Array<String>) {
    //传统调用函数的方式,根据位置传入参数
    girth(3.5, 4.9)
    //根据参数名来传入参数
    girth(width = 3.5, height = 4.9)
    //使用命名参数是可交换位置
    girth(height = 4.9, width = 3.5)
    //部分使用命名参数,部分使用位置参数  混合使用时命名参数必须位于位置参数之后
    girth(3.5, height = 4.9)
}

形参默认值

在某些情况下,程序需要在定义函数时为一个或多个形参指定默认值,这样调用函数时就可以省略该形参,而直接使用默认值。为形参指定默认值的语法如下:

形参名: 形参类型 = 默认值

如果在定义函数时将有默认值的参数放在了普通参数的前面,并且不想为默认参数重新传入参数值,那么就只能使用命名参数为其他参数传入参数值。所以不建议这种写法。


//形参默认值
fun sayHi(name: String = "xq", msg: String = "welcome") {
    println("name: $name ,msg: $msg")
}

fun printTriangle(height: Int = 5, char: Char) {
    for (i in 1..height) {
        for (j in 0 until height - 1) {
            print(" ")
        }

        for (j in 0 until 2 * i - 1) {
            print(char)
        }
        println()
    }

}
fun main(args: Array<String>) {
    //全部使用默认值
    sayHi()
    //只有msg使用默认值
    sayHi("xy")
    //2个都不使用默认值
    sayHi("sqq", "hi")
    //只有name使用默认值
    sayHi(msg = "你好")

    printTriangle(6, '@')
    printTriangle(7, char = '#')
    printTriangle(char = '*')
}

尾递归函数

kotlin还支持一种尾递归函数的编程方式,当函数将调用自身作为它执行的最后一行代码,且递归调用之后没有更多代码时,可以使用尾递归语法。另外尾递归不能再异常处理的try,catch,finally中使用,尾递归需要使用tailrec修饰。


//尾递归函数
fun fact(n: Int): Int {
    return when (n) {
        1 -> 1
        else -> n * fact(n - 1)
    }
}
tailrec fun factRec(n: Int, total: Int = 1): Int =
//if (n == 1) total else factRec(n - 1, total * n)
        when (n) {
            1 -> total
            else -> factRec(n - 1, total * n)
        }

fun main(args: Array<String>) {
    println("fact(10): ${fact(10)}")
    println("factRec(10):${factRec(10)}")
}

尾递归函数的优势:与普通递归相比,编译器会对尾递归进行修改,将其优化成一个快速而高效的基于循环的版本,这样就可以减少可能对内存的消耗。

个数可变的形参

kotlin允许定义个数可变的参数,从而为函数指定数量不确定的形参,如果在定义函数时,在形参的类型前面添加了vararg修饰,则表明该形参可以接受多个参数值,多个参数值被当做数组传入。

kotlin允许个数可变的形参处于形参列表的任何位置,但是要求一个函数最多只能有一个个数可变的形参,如果个数可变的形参位于参数列表的第一个,因此如果给后面参数赋值时必须使用命名参数。


//个数可变的形参
fun test(a: Int, vararg books: String) {
    for (b in books) {
        println(b)
    }
    println(a)
}
fun main(args: Array<String>) {
    test(2, "java", "kotlin")
}

函数重载

kotlin允许定义多个同名函数,只要它们的形参列表或者返回值类型不同就行。如果程序包含了2个或者以上函数名相同,但是仅有参数列表不同的函数,就被成为函数重载。


fun test(a: Int, vararg books: String) {
    for (b in books) {
        println(b)
    }
    println(a)
}

//函数的重载
fun test() {
    println("函数的重载,上面是有参的函数")
}

fun main(args: Array<String>) {
    test(2, "java", "kotlin")
    test()
}

局部函数

之前我们所看到的函数都是在全局范围内定义的,它们都是全局函数,kotlin还支持在函数体内部定义函数,这种函数称为局部函数。

在默认的情况下,局部函数都是对外部隐藏的,局部函数只能在其封闭的函数体内有效,其封闭函数也可以返回局部函数,以便程序在其他作用域中使用局部函数。


//局部函数
fun mathFunc(type: String, nn: Int): Int {
    fun square(n: Int): Int {
        return n * n
    }

    fun cube(n: Int): Int {
        return n * n * n
    }

    when (type) {
        "square" -> return square(nn)
        "cube" -> return cube(nn)
        else -> return 0
    }
}



fun main(args: Array<String>) {
    println(mathFunc("square", 3))
}

相关文章

  • lambda表达式

    什么是lambda表达式 lambda表达式的本质 lambda表达式是一种匿名函数,匿名函数是函数定义不绑定到任...

  • Python基础——匿名函数+作用域

    一、匿名函数:lambda 函数名 = lambda 参数: 表达式 1、有名函数 2、匿名函数lambda [ ...

  • python第21课练习—lambda表达式

    1、请使用lambda表达式将下边函数转化为匿名函数? lambda表达式lambda表达式,通常是在需要一个函数...

  • 第二章 Lambda表达式

    引入Lambda表达式后: 编写Lambda表达式的不同形式: Lambda表达式本身的类型:函数接口 函数接口 ...

  • Lambda表达式

    Lambda表达式与函数式接口紧密相关,函数式接口介绍 Lambda表达式的基本语法 Java Lambda表达式...

  • Lambda

    一、表达式 1.1 Lambda表达式格式: 1.2 有效的Lambda表达式 1.3 Lambda示例 二、函数...

  • 《Java 8实战》学习总结

    Java 8新特性概览 Lambda表达式 流 默认方法 Lambda表达式 Lambda和函数式接口Java 8...

  • Kotlin学习之高阶函数和Lambda表达式:闭包

    Kotlin学习之高阶函数和Lambda表达式:闭包 一、闭包 闭包指Lambda表达式和匿名函数外部定义的局部变...

  • C++ Lambda函数与表达式

    C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。 Lambda 表达式...

  • 深入浅出的了解C# Lambda表达式

    Lambda表达式 "Lambda表达式"是一个匿名函数,是一种高效的类似于 函数式编程的表达式,Lambda简化...

网友评论

      本文标题:函数和Lambda表达式(一)

      本文链接:https://www.haomeiwen.com/subject/fdtyoftx.html