当前位置: 首页 > article >正文

kotlin教程4:函数进阶

文章目录

    • 可变参数
    • 尾递归函数
    • 函数式

kotlin教程:编程基础💎数据结构💎面向对象

可变参数

kotlin的函数定义非常灵活,既可以按照顺序传参,也可以通过参数名传参,而且可以设置参数默认值,这些在基础教程中已经讲过了。

此外,kotlin中用vararg修饰的参数,为长度可变的参数列表

fun printLst(vararg ts: Int){
    for(t in ts){
        println(t)
    }
}

printLst(1,2,3)
/*
1
2
3
*/

尾递归函数

递归是一种常用的编程技巧,就像之前写的递归式阶乘

fun fac(n:Int):Int{return if(n>1) n*fac(n-1) else 1}

但递归有一个很重要的缺点,即每次调用都要在栈中保存上一个函数的返回地址,如果递归层数太多,会导致栈溢出,所以很多时候会将递归算法改写成动态规划。

为了解决递归问题,kotlin提供了尾递归方案,即通过tailrec修饰的函数,如果在函数的最后一行调用自身,那么编译器将自动将递归函数转成迭代形式,而无需担心堆栈错误。

为了理解什么是尾递归,下面以斐波那契数列举个例子

fun fib(n:Int):Int{
    if(n<3)
        return 1
    else
        return fib(n-1)+fib(n-2)
}
fun main(){
    println(fib(215))
}

这个函数尽管在最后一行调用了自身,但调用自身后还有一个相加的操作,所以是不符合尾递归的要求的。

对此可将其改写为

fun fib(n:Long, a: Long, b: Long): Long {
    if (n < 1) return a
    else return fib(n-1, b, a + b)
}

这就是尾递归的形式。对比这两种不同的递归方案可以发现,第一种运行之后会卡住,在短时间内没法得出结果,后者则轻而易举地得出了。

>kotlin test.jar
319982248

当然,这个过程并没有使用tailrec关键字,所以当n的值比较大的时候一样会出问题

fun main(){
    println(fib(12000, 1, 1))
}

会报这个错误

Exception in thread "main" java.lang.StackOverflowError
        at TestKt.fib(test.kt:3)

下面可测试一下编译优化的效果

tailrec fun fib(n:Long, a: Long, b: Long): Long {
    if (n < 1) return a
    else return fib(n-1, b, a + b)
}

fun main(){
    println(fib(12000, 1, 1))
}

编译运行,顺利得出结果

>kotlin test.jar
3221758877563775297

函数式

所谓函数式,从敲代码的角度出发,就是把函数作为一种数据类型,可以自由地作为其他函数的参数与返回值。

由于Kotlin中,函数中所有的参数和返回值都要声明数据类型,所以,函数在作为参数传递时,也要标明函数的输入输出返回值,例如下面代码是函数作为参数的一个例子

fun testFunc(func:(Int)->Int) : (Double)->Double{
    return {a:Double -> func(a.toInt()).toDouble()}
}

fun test1(func:(Int)->Int):Int{
    return func(5)
}

其中,func:(Int)->Int为输入参数,func为参数名,(Int)->Intfunc作为一种函数的输入输出声明,表示func是一个输入Int输出Int的函数。

(Double)->DoubletestFunc的返回值类型,表示一个输入Double输出Double函数。

换言之testFunc的功能是,将一个输入输出均为整型的函数,转化为输入输出均为浮点型的函数。

return{ -> }是一个匿名函数,这个在最开始介绍函数的时候就已经讲过了。

接下来测试一下,先新建一个输入整型输出整型的函数

fun square(a:Int):Int{return a*a}
square(3)   // 返回值 kotlin.Int = 9
square(3.0) //报错

然后转换,需要注意,当函数作为参数传递时,需要用::标识

testFunc(::square)(3.0) //返回值9.0

也可以新建一个函数

val dSquare = testFunc(::square)
dSquare(3.0)    //kotlin.Double = 9.0

http://www.kler.cn/a/15926.html

相关文章:

  • c++入门--引用与指针,const与引用,NULL与nullptr
  • A030-基于Spring boot的公司资产网站设计与实现
  • 掌握C#中的异步编程:async和await关键字详解
  • 深度解析:Android APP集成与拉起微信小程序开发全攻略
  • 删库跑路,启动!
  • Go八股(Ⅴ)map
  • 贪心算法OJ刷题(2)
  • Python并发编程之进程操作
  • aac音频怎么转mp3,这几个方法很简便
  • 2023五一杯B题赛题公布
  • OpenGL(三)——着色器
  • Redis学习笔记01 (数据结构,线程模型,持久化)
  • 分屏视图上线,详情数据秒切换
  • Python小姿势 - # 如何在Python中实现基本的数据类型
  • 如何查看自己是否使用了国产SSL证书?“套牌”SSL证书?
  • GDB 1、超详细的GDB入门笔记,包含演示代码,快速入门
  • Prompt炼丹炉——一系列Prompt自动优化的实践记录
  • python使用公共api下载狗狗图片
  • Cadence基础操作:Schematic编辑
  • vue+element Ui 树型组件tree懒加载+搜索框远程请求数据为平铺类型
  • TF-IDF (BigData, Data Mining)
  • 【LeetCode: 62. 不同路径 | 暴力递归=>记忆化搜索=>动态规划 】
  • 设计模式-适配器模式
  • RabbitMQ 工作队列模式 Work Queue Demo
  • C S S
  • 制药专业转行软件测试,带我的师傅在这干了两年半,最终还是跑路了......