函数:

1.函数声明

  kotlin中的函数使用fun关键字声明:

fun double(x: Int): Int {
return 2 * x
}

2.函数用法

  调用函数使用传统的方法:

val result = double(2)

  调用成员函数使用点表示法:

Stream().read() // 创建类 Stream 实例并调用 read()

3. 参数

  函数参数使用 Pascal 表示法定义,即 name: type。参数用逗号隔开。每个参数必须有显式类型:

fun powerOf(number: Int, exponent: Int) { /*......*/ }

4.默认参数

  函数参数可以有默认值,当省略相应的参数时使用默认值。与其他语言相比,这可以减少重载数量

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) { /*......*/ }

  默认值通过类型后面的 = 及给出的值来定义

  覆盖方法总是使用与基类型方法相同的默认参数值。当覆盖一个带有默认参数值的方法时,必须从签名 中省略默认参数值:

open class A {
open fun foo(i: Int = 10) { /*......*/ }
} class B : A() {
override fun foo(i: Int) { /*......*/ } // 不能有默认值
}

  如果一个默认参数在一个无默认值的参数之前,那么该默认值只能通过使用具名参数调用该函数来使 用:

fun foo(bar: Int = 0, baz: Int) { /*......*/ }
foo(baz = 1) // 使用默认值 bar = 0

  如果在默认参数之后的最后一个参数是 lambda 表达式,那么它既可以作为具名参数在括号内传入,也 可以在括号外传入

fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /*......*/ }

foo(1) { println("hello") } // 使用默认值 baz = 1
foo(qux = { println("hello") }) // 使用两个默认值 bar = 0 与 baz = 1 foo { println("hello") } // 使用两个默认值 bar = 0 与 baz = 1

5.具名参数

  可以在调用函数时使用具名的函数参数。当一个函数有大量的参数或默认参数时这会非常方便。

  给定以下函数:

fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ') {
/*......*/
}

  我们可以使用默认参数来调用它:

reformat(str)

  然而,当使用非默认参数调用它时,该调用看起来就像:

reformat(str, true, true, false, '_')

  使用具名参数我们可以使代码更具有可读性:

reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_'
)

  并且如果我们不需要所有的参数:

reformat(str, wordSeparator = '_')

  当一个函数调用混用位置参数与具名参数时,所有位置参数都要放在第一个具名参数之前。例如,允许

调用 f(1, y = 2) 但不允许 f(x = 1, 2)。

  可以通过使用星号操作符将可变数量参数(vararg)以具名形式传入:

fun foo(vararg strings: String) { /*......*/ } 

foo(strings = *arrayOf("a", "b", "c"))

//对于 JVM 平台:在调用 Java 函数时不能使用具名参数语法,因为 Java 字节码并不总是保留函数 参数的名称。

6.返回Unit的函数

  如果一个函数不返回任何有用的值,它的返回类型是 Unit 。Unit 是一种只有一个值⸺ Unit 的类 型。这个值不需要显式返回

fun printHello(name: String?): Unit {
if (name != null)
println("Hello $name") else
println("Hi there!")
// `return Unit` 或者 `return` 是可选的
}

  Unit 返回类型声明也是可选的。上面的代码等同于:

fun printHello(name: String?) { ...... }

7.单表达式函数

  当函数返回单个表达式时,可以省略花括号并且在 = 符号之后指定代码体即可:

fun double(x: Int): Int = x * 2

  当返回值类型可由编译器推断时,显式声明返回类型是可选的:

fun double(x: Int) = x * 2

8.显示返回类型

  具有块代码体的函数必须始终显式指定返回类型,除非他们旨在返回 Unit,在这种情况下它是可选 的。Kotlin 不推断具有块代码体的函数的返回类型,因为这样的函数在代码体中可能有复杂的控制流,

并且返回类型对于读者(有时甚至对于编译器)是不明显的。

9.可变数量的参数(Varargs)

  函数的参数(通常是最后一个)可以用 vararg 修饰符标记:

fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) // ts is an Array
result.add(t)
return result
}

  允许将可变数量的参数传递给函数:

val list = asList(1, 2, 3)

  在函数内部,类型 T 的 vararg 参数的可⻅方式是作为 T 数组,即上例中的 ts 变量具有类型Array <out T>。

  只有一个参数可以标注为 vararg 。如果 vararg 参数不是列表中的最后一个参数,可以使用具名参数语法传递其后的参数的值,或者,如果参数具有函数类型,则通过在括号外部传一个 lambda。

  当我们调用 vararg -函数时,我们可以一个接一个地传参,例如 asList(1, 2, 3) ,或者,如果我们已经有一个数组并希望将其内容传给该函数,我们使用伸展(spread)操作符(在数组前面加 * ):

val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)

10.中缀表示法

//标有 infix 关键字的函数也可以使用中缀表示法(忽略该调用的点与圆括号)调用。中缀函数必须满足 以下要求:
//— 它们必须是成员函数或扩展函数;
//— 它们必须只有一个参数;
//— 其参数不得接受可变数量的参数且不能有默认值。 infix fun Int.shl(x: Int): Int { ...... } // 用中缀表示法调用该函数
1 shl 2 // 等同于这样
1.shl(2) //中缀函数调用的优先级低于算术操作符、类型转换以及 rangeTo 操作符。以下表达式是等价 的:
//— 1 shl 2 + 3等价于1 shl (2 + 3)
//— 0 until n * 2等价于0 until (n * 2)
//— xs union ys as Set<*>等价于xs union (ys as Set<*>)
//另一方面,中缀函数调用的优先级高于布尔操作符 && 与 ||、is- 与 in- 检测以及其他一些操 作符。这些表达式也是等价的:
//— a && b xor c等价于a && (b xor c)
//— a xor b in c等价于(a xor b) in c

  请注意,中缀函数总是要求指定接收者与参数。当使用中缀表示法在当前接收者上调用方法时,需要显 式使用 this ;不能像常规方法调用那样省略。这是确保非模糊解析所必需的

class MyStringCollection {
infix fun add(s: String) { /*......*/
} fun build() {
this add "abc"// 正确
add("abc")// 正确
add "abc" // 错误:必须指定接收者
}
}

11.函数作用域

  在 Kotlin 中函数可以在文件顶层声明,这意味着你不需要像一些语言如 Java、C# 或 Scala 那样需要创 建一个类来保存一个函数。此外除了顶层函数,Kotlin 中函数也可以声明在局部作用域、作为成员函数 以及扩展函数。

12.局部函数

  Kotlin 支持局部函数,即一个函数在另一个函数内部:

fun dfs(graph: Graph) {
fun dfs(current: Vertex, visited: MutableSet<Vertex>) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v, visited)
}
dfs(graph.vertices[0], HashSet())
}

  局部函数可以访问外部函数(即闭包)的局部变量,所以在上例中,visited 可以是局部变量:

fun dfs(graph: Graph) {
val visited = HashSet<Vertex>()
fun dfs(current: Vertex) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v)
}
dfs(graph.vertices[0])
}

13.成员函数

  成员函数是在类或对象内部定义的函数:

class Sample {
fun foo() { print("Foo") }
}

  成员函数以点表示法调用:

Sample().foo() // 创建类 Sample 实例并调用 foo

14.泛型函数

  函数可以有泛型参数,通过在函数名前使用尖括号指定:

fun <T> singletonList(item: T): List<T> { /*......*/ }

15.尾递归函数

  Kotlin支持一种称为尾递归的函数式编程风格。这允许一些通常用循环写的算法改用递归函数来写,而无堆栈溢出的风险。当一个函数用tailrec修饰符标记并满足所需的形式时,编译器会优化该递归,留下一个快速而高效的基于循环的版本:

val eps = 1E-10 // "good enough", could be 10^-15
tailrec fun findFixPoint(x: Double = 1.0): Double
= if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))

  这段代码计算余弦的不动点(fixpoint of cosine),这是一个数学常数。它只是重复地从 1.0 开始调用 Math.cos,直到结果不再改变,对于这里指定的 eps 精度会产生 0.7390851332151611 的结果。最终代码相当于这种更传统⻛格的代码:

val eps = 1E-10 // "good enough", could be 10^-15

private fun findFixPoint(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if (Math.abs(x - y) < eps) return x
x = Math . cos (x)
}
} //要符合 tailrec 修饰符的条件的话,函数必须将其自身调用作为它执行的最后一个操作。
//在递归调用后有更多代码时,不能使用尾递归,并且不能用在try/catch/finally 块中。
//目前在 Kotlin for JVM 与 Kotlin/Native 中支持尾递归。

  

kotlin函数和Lambda表达式——>函数的更多相关文章

  1. Kotlin语法(函数和lambda表达式)

    三.函数和lambda表达式 1. 函数声明 fun double(x: Int): Int { } 函数参数是用 Pascal 符号定义的 name:type.参数之间用逗号隔开,每个参数必须指明类 ...

  2. 《疯狂Kotlin讲义》读书笔记6——函数和Lambda表达式

    函数和Lambda表达式 Kotlin融合了面向过程语言和面向对象语言的特征,相比于Java,它增加了对函数式编程的支持,支持定义函数.调用函数.相比于C语言,Kotlin支持局部函数(Lambda表 ...

  3. 浅析匿名函数、lambda表达式、闭包(closure)区别与作用

    浅析匿名函数.lambda表达式.闭包(closure)区别与作用 所有的主流编程语言都对函数式编程有支持,比如c++11.python和java中有lambda表达式.lua和JavaScript中 ...

  4. 委托,匿名函数和lambda表达式

    很早之前就接触到了委托,但是一直对他用的不是太多,主要是本人是菜鸟,能写的比较高级的代码确实不多,但是最近在看MSDN微软的类库的时候,发现了微软的类库好多都用到了委托,于是决定好好的研究研究,加深一 ...

  5. 匿名函数:Lambda表达式和匿名方法

    匿名函数一个"内联"语句或表达式,可在需要委托类型的任何地方使用.可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. 共有两种匿名函数: Lamb ...

  6. python函数,lambda表达式,三目运算,列表解析,递归

    一.自定义函数 定义函数时,函数体不执行:只有在调用函数时,函数体才执行.函数的结构: 1. def 2. 函数名 3. 函数体 def func_name(): 函数体 4. 返回值 如果没有声明返 ...

  7. python3 入门 (三) 函数与lambda表达式、闭包

    函数 是组织好的.可重复使用的.用来实现单一或相关联功能的代码段. 函数代码块以def关键词开头,后接函数标识符名称和圆括号() 任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用于定义参数 函 ...

  8. 3 委托、匿名函数、lambda表达式

    委托.匿名函数.lambda表达式 在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法.C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方 ...

  9. C#语法之匿名函数和Lambda表达式

    上一篇博客主要是对委托和事件做了一小结,这篇是在上一篇博客的基础上对匿名函数和Lambda表达式小结.还是接着上一篇说起,在上一篇中也说了委托是一种数据结构,主要是解决让函数作为参数的问题.在使用委托 ...

  10. Python内嵌函数与Lambda表达式

    //2018.10.29 内嵌函数与lambda 表达式 1.如果在内嵌函数中需要改变全局变量的时候需要用到global语句对于变 量进行一定的说明与定义 2.内部的嵌套函数不可以直接在外部进行访问 ...

随机推荐

  1. 【RabbitMQ】03 订阅模式

    Pub / Sub 订阅模式 特点是 一条消息可以给多个消费者接收了 首先创建订阅模式生产者发生一些代码变动: package cn.dzz.pubSub; import com.rabbitmq.c ...

  2. centos7系统 通过编译安装gcc7.5.0

    背景: 现有的centos7 gcc的最高版本为4.8.5 项目需要升级到7.1.0以上 正常方式可以通过以下命令即可完成升级: $ sudo yum install centos-release-s ...

  3. 使用 Apache DolphinScheduler 进行 EMR 任务调度

    By AWS Team 前言 随着企业规模的扩大,业务数据的激增,我们会使用 Hadoop/Spark 框架来处理大量数据的 ETL/聚合分析作业,⽽这些作业将需要由统一的作业调度平台去定时调度. 在 ...

  4. Python 提取出SQL语句中Where的值的方法

    1.方法一:使用sqlparse库的方法 为了提取SQL语句中WHERE子句的值,我们可以利用Python的sqlparse库,这是一个专门用于解析SQL语句的库.以下是一个示例代码,演示如何使用sq ...

  5. 018.CentOS升级内核

    一 更新yum源 1 [root@localhost ~]# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org 2 [root@lo ...

  6. PHP转Go系列 | ThinkPHP与Gin框架之打造基于WebSocket技术的消息推送中心

    大家好,我是码农先森. 在早些年前客户端想要实时获取到最新消息,都是使用定时长轮询的方式,不断的从服务器上获取数据,这种粗暴的骚操作实属不雅.不过现如今我也还见有人还在一些场景下使用,比如在 PC 端 ...

  7. 什么是ARM中的SP(堆栈)和LR?

    LR是用于保存函数调用的返回地址的link register. SP是堆栈指针.堆栈通常用于在函数调用中保存"automatic"变量和上下文/参数.从概念上讲,您可以将" ...

  8. C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)

    前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用的技术文章.社区动态.优质项目和学习资源等.让你时刻站 ...

  9. Typora中的markdown语法的学习

    markdown语法学习 二级标题 三级标题 四级标题 字体 hello world hello world hello world hello world 引用 我是最nb的 分割线 图片 ctrl ...

  10. zabbix基本概念

    Zabbix是一个企业级的.开源的.分布式监控解决方案. Zabbix可以监控网络和服务的监控状况. Zabbix利用灵活的告警机制,允许用户对事件发送基于Email的告警. 这样可以保证快速的对问题 ...