仓颉开发之——函数(6)
一 概述
- 定义函数
- 调用函数
- 函数类型
- 嵌套函数
- Lambda表达式
- 闭包
- 函数语法糖调用
- 函数重载
- 操作符重载
二 定义函数
2.1 定义函数
1 | func add(a: Int64, b: Int64): Int64 { |
说明:
- 使用关键字
func
定义函数 - func 之后依次是函数名、参数列表、可选的函数返回值类型、函数体
2.2 参数列表
1 | func add(a!: Int64 = 1, b!: Int64 = 1): Int64 { |
说明:
- 参数列表中的参数分为两类:非命名参数和命名参数
- 非命名参数的定义方式是 p: T,其中 p 表示参数名,T 表示参数 p 的类型,参数名和其类型间使用冒号连接
- 命名参数的定义方式是 p!: T,与非命名参数的不同是在参数名 p 之后多了一个 !
- 命名参数还可以设置默认值,通过 p!: T = e 方式将参数 p 的默认值设置为表达式 e 的值
三 调用函数
3.1 非命名参数调用
1 | func add(a: Int64, b: Int64) { |
执行结果
1 | The sum of x and y is 3 |
3.2 命名参数调用
1 | func add(a!: Int64, b!: Int64) { |
执行结果
1 | The sum of x and y is 3 |
说明:
- 命名参数调用时须知名参数
四 函数类型
4.1 概念
函数类型由函数的参数类型和返回类型组成,参数类型和返回类型之间使用 -> 连接
1 | func hello(): Unit { |
说明:
- 上述示例定义了一个函数,函数名为 hello
- 其类型是 () -> Unit,表示该函数没有参数,返回类型为 Unit
4.2 函数类型作为参数类型
1 | func add(a: Int64, b: Int64): Int64 { |
五 嵌套函数
5.1 概念
定义在源文件顶层的函数被称为全局函数。定义在函数体内的函数被称为嵌套函数
5.2 示例
1 | func foo() { |
输出结果
1 | 6 |
说明:定义f,f返回的结果为nestAdd,可以调用(Int64,Int64)->Int64
六 Lambda表达式
6.1 Lambda表达式定义
Lambda 表达式的语法为如下形式: { p1: T1, ..., pn: Tn => expressions | declarations }。
1 | let f1 = { a: Int64, b: Int64 => a + b } |
说明:
- Lambda 表达式不管有没有参数,都不可以省略 =>,除非其作为尾随 lambda
6.2 Lambda 表达式调用
1 | //1-立即调用 |
七 闭包
7.1 概念
闭包就是能够读取其他函数内部变量的函数或函数或 lambda 和捕获的变量一起被称为一个闭包
7.2 其他
- 变量捕获
- 变量捕获规则
八 函数语法糖调用
8.1 尾随 lambda
1-说明
- 当函数最后一个形参是函数类型,并且函数调用对应的实参是 lambda 时
- 我们可以使用尾随 lambda 语法,将 lambda 放在函数调用的尾部,圆括号外面
2-示例
1 | func myIf(a: Bool, fn: () -> Int64) { |
8.2 Flow 表达式
流操作符包括两种:表示数据流向的中缀操作符 |> (称为 pipeline)和表示函数组合的中缀操作符 ~> (称为 composition)
1-Pipeline 表达式(e1 |> e2。等价于如下形式的语法糖:let v = e1; e2(v) )
1 | func inc(x: Array<Int64>): Array<Int64> { // Increasing the value of each element in the array by '1' |
2-Composition 表达式(f ~> g。等价于如下形式: { x => g(f(x)) })
1 | func f(x: Int64): Float64 { |
8.3 变长参数
当形参最后一个非命名参数是 Array 类型时,实参中对应位置可以直接传入参数序列代替 Array
1 | func sum(arr: Array<Int64>) { |
九 函数重载
9.1 函数重载定义
- 函数名相同,函数参数不同(是指参数个数不同,或者参数个数相同但参数类型不同)的两个函数构成重载
- 对于两个同名泛型函数,如果重命名一个函数的泛型形参后,其非泛型部分与另一个函数的非泛型部分函数参数不同,则两个函数构成重载
- 同一个类内的两个构造函数参数不同,构成重载
- 同一个类内的主构造函数和 init 构造函数参数不同,构成重载
- 两个函数定义在不同的作用域,在两个函数可见的作用域中构成重载。
- 两个函数分别定义在父类和子类中,在两个函数可见的作用域中构成重载
9.2 函数重载决议
函数调用时,所有可被调用的函数(是指当前作用域可见且能通过类型检查的函数)构成候选集,候选集中有多个函数,究竟选择候选集中哪个函数,需要进行函数重载决议
十 操作符重载
10.1 可重载操作符
No | 操作符 | 描述 |
---|---|---|
1 | () | Function call |
2 | [] | Indexing |
3 | ! | NOT |
4 | - | Negative |
5 | ** | Power |
6 | * | Multiply |
7 | / | Divide |
8 | % | Remainder |
9 | + | Add |
10 | - | Subtract |
10.2 示例
1 | open class Point { |
十一 思维导图
十二 参考
- 仓颉—函数
- 仓颉语言入门教程