泛型函数
如果一个函数声明了一个或多个类型形参,则将其称为泛型函数。语法上,类型形参紧跟在函数名后,并用 <>
括起,如果有多个类型形参,则用“,”分离。
全局泛型函数
在声明全局泛型函数时,只需要在函数名后使用尖括号声明类型形参,然后就可以在函数形参、返回类型及函数体中对这一类型形参进行引用。例如 id
函数定义为:
func id<T>(a: T): T {
return a
}
其中 (a: T)
是函数声明的形参,其中使用到了 id
函数声明的类型形参 T
,并且在 id
函数的返回类型使用。
再比如另一个复杂的例子,定义如下一个泛型函数 composition
,该函数声明了 3 个类型形参,分别是 T1, T2, T3
,其功能是把两个函数 f: (T1) -> T2, g: (T2) -> T3
复合成类型为 (T1) -> T3
的函数。
func composition<T1, T2, T3>(f: (T1) -> T2, g: (T2) -> T3): (T1) -> T3 {
return {x: T1 => g(f(x))}
}
因为被用来复合的函数可以是任意类型,例如可以是 (Int32) -> Bool, (Bool) -> Int64
的复合,也可以是 (Int64) -> Rune, (Rune) -> Int8
的复合,所以才需要使用泛型函数。
func times2(a: Int64): Int64 {
return a * 2
}
func plus10(a: Int64): Int64 {
return a + 10
}
func times2plus10(a: Int64) {
return composition<Int64, Int64, Int64>(times2, plus10)(a)
}
main() {
println(times2plus10(9))
return 0
}
这里,我们复合两个 (Int64) -> Int64
的函数,将 9 先乘以 2,再加 10,结果会是 28。
28
局部泛型函数
局部函数也可以是泛型函数。例如泛型函数 id
可以嵌套定义在其它函数中:
func foo(a: Int64) {
func id<T>(a: T): T { a }
func double(a: Int64): Int64 { a + a }
return (id<Int64> ~> double)(a) == (double ~> id<Int64>)(a)
}
main() {
println(foo(1))
return 0
}
这里由于 id
的单位元性质,函数 id<Int64> ~> double
和 double ~> id<Int64>
是等价的,结果是 true
。
true
泛型成员函数
class、struct 与 enum 的成员函数可以是泛型的。例如:
class A {
func foo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
struct B {
func bar<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
enum C {
| X | Y
func coo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
main() {
var a = A()
var b = B()
var c = C.X
a.foo<Int64>(10)
b.bar<String>("abc")
c.coo<Bool>(false)
return 0
}
程序输出的结果为:
10
abc
false
这里需要注意的是,class 中声明的泛型成员函数不能被 open 修饰,如果被 open 修饰则会报错,例如:
class A {
public open func foo<T>(a: T): Unit where T <: ToString { // Error, open generic function is not allowed
println("${a}")
}
}
在为类型使用 extend 声明进行扩展时,扩展中的函数也可以是泛型的,例如我们可以为 Int64
类型增加一个泛型成员函数:
extend Int64 {
func printIntAndArg<T>(a: T) where T <: ToString {
println(this)
println("${a}")
}
}
main() {
var a: Int64 = 12
a.printIntAndArg<String>("twelve")
}
程序输出的结果将为:
12
twelve
静态泛型函数
interface、class、struct、enum 与 extend 中可以定义静态泛型函数,例如下例 ToPair
class 中从 ArrayList
中返回一个元组:
import std.collection.*
class ToPair {
public static func fromArray<T>(l: ArrayList<T>): (T, T) {
return (l[0], l[1])
}
}
main() {
var res: ArrayList<Int64> = ArrayList([1,2,3,4])
var a: (Int64, Int64) = ToPair.fromArray<Int64>(res)
return 0
}