The Swift Programming Language学习笔记(七)——函数
函数Swift统一的函数语法足够灵活,可以用来表示任何函数,包括从最简单的没有参数名字的C风格函数,到复杂的带局部和外部参数名的Objective-C风格函数。参数可以提供默认值,以简化函数调用。参数也可以既当做传入参数,也当做传出参数,也就是说,一旦函数执行结束,传入的参数值可以被修改。 在Swift中,每个函数都有一种类型,包括函数的参数值类型和返回值类型。你可以把函数类型当做任何其他普通变量类型一样处理,这样就可以更简单地把函数当做别的函数的参数,也可以从其他函数中返回函数。函数的定义可以写在其他函数定义中,这样可以在嵌套函数范围内实现功能封装。 函数定义与调用函数以 func sayHello(personName: String) -> String {
return "Hello," + personName + "!"
}
print(sayHello("Tim"))
函数参数与返回值无参函数函数可以没有参数。尽管没有参数,但是定义中在函数名后还是需要一对圆括号。当被调用时,也需要在函数名后写一对圆括号。 多参数函数参数被包含在函数的括号之中,以逗号分隔。当调用超过一个参数的函数时,第一个参数后的参数根据其对应的参数名称标记。 无返回值函数函数可以没有返回值。此时,函数的定义中没有 多重返回值函数用元组(tuple)类型让多个值作为一个复合值从函数中返回,通过 func minmax(arr: [Int]) -> (min: Int,max: Int) {
var min = arr[0]
var max = arr[0]
for data in arr[1..<arr.count] { // 从1开始
if data < min {
min = data
} else if data > max {
max = data
}
}
return (min,max)
}
let data = [1,2,34,1,11,-1]
let a = minmax(data)
print(a.min)
print(a.max)
可选元组返回类型如果函数返回的元组类型有可能整个元组都“没有值”,你可以使用可选的(Optional) 元组返回类型反映整个元组可以是nil的事实。你可以通过在元组类型的右括号后放置一个问号来定义一个可选元组。注意:可选元组类型如 // 为了安全地处理“空数组”问题,将返回值改为可选元组返回类型,并且当数组为空时返回nil。
func minmax(arr: [Int]) -> (min: Int,max: Int)? {
if arr.isEmpty {
return nil
}
var min = arr[0]
var max = arr[0]
for data in arr[1..<arr.count] { // 从1开始
if data < min {
min = data
} else if data > max {
max = data
}
}
return (min,max)
}
let data = [1,-1] // let data = [Int]()
let a = minmax(data)
print(a) // Optional((-1,34))
if let b = a {
print(b.min)
print(b.max)
} else {
print("array is empty")
}
函数参数名称函数参数都有一个外部参数名(external parameter name)和一个局部参数名(local parameter name)。外部参数名用于在函数调用时标注传递给函数的参数,局部参数名在函数的实现内部使用。 一般情况下,第一个参数省略其外部参数名,第二个以及随后的参数使用其局部参数名作为外部参数名。所有参数必须有独一无二的局部参数名。尽管多个参数可以有相同的外部参数名,但不同的外部参数名能让你的代码更有可读性。 指定外部参数名可以在局部参数名前指定外部参数名,中间以空格分隔。如果你提供了外部参数名,那么函数在被调用时,必须使用外部参数名。 为每个参数指定外部参数名后,在调用时所有外部参数名都必须写出来。使用外部函数名可以使函数以一种更富有表达性的类似句子的方式调用,并使函数体意图清晰,更具可读性。 func sayHello(from sender: String,to receiver: String) {
print("(sender) says to (receiver),Hello!!!")
}
sayHello(from: "Tim",to: "Kate") // Tim says to Kate,Hello!!!
忽略外部参数名如果不想为第二个及后续的参数设置外部参数名,用一个下划线( func sayHello(sender: String,_ receiver: String) { // 使用_免去设置后面的外部参数名,而第一个也没必要写外部参数名,默认是忽略的
print("(sender) says to (receiver),Hello!!!")
}
sayHello("Tim","Kate") // Tim says to Kate,Hello!!!此时无需设置第2个之后的参数名!
默认参数值可以在函数体中为每个参数定义 将带有默认值的参数放在函数参数列表的最后。这样可以保证在函数调用时,非默认参数的顺序是一致的,同时使得相同的函数在不同情况下调用时显得更为清晰。 func hello(name: String = "World") {
print("Hello,(name)!!!")
}
hello("Tim")
hello()
可变参数一个 一个函数最多只能有一个可变参数。如果函数有一个或多个带默认值的参数,而且还有一个可变参数,那么把可变参数放在参数表的最后。 func mean(numbers: Double...) -> Double {
if numbers.isEmpty {
return 0.0
}
var sum = 0.0
for number in numbers {
sum += number
}
return sum / Double(numbers.count)
}
print(mean()) // 不判断是否是空数组,结果就是nan
print(mean(1.1,2.2))
print(mean(2.2,44.3,33,3232,1111))
常量参数和变量参数函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误。这意味着你不能错误地更改参数值。 但是有时候,如果函数中有传入参数的变量值副本将是很有用的。你可以通过指定一个或多个参数为变量参数,从而避免自己在函数中定义新的变量。变量参数不是常量,你可以在函数中把它当做新的可修改副本来使用。通过在参数名前加关键字 func f1(data: Int) {
// data = 1 // error: cannot assign to value: 'data' is a 'let' constant
}
func f2(var data: Int) -> Int {
++data
return data
}
let a = 10
print(f2(a)) // 11
此时,data就是仅函数内可见的局部变量,被传入的a初始化后,并在函数体中进行操作。 输入输出参数前面的变量参数仅仅能在函数体内被更改。如果想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数(In-Out Parameters)。 定义一个输入输出参数时,在参数定义前加 只能传递变量给输入输出参数。不能传入常量或者字面量(literal value),因为这些量是不能被修改的。当传入的参数作为输入输出参数时,需要在参数名前加 输入输出参数不能有默认值,而且可变参数不能用 func swapInt(inout a: Int,inout _ b: Int) {
let c = a
a = b
b = c
}
var m = 10
var n = 20
swapInt(&m,&n)
print(m)
print(n)
此时,虽然 输入输出参数和返回值是不一样的。上面的函数没有返回值却依然影响了参数。输入输出参数是函数对函数体外产生影响的另一种方式。 函数类型每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。 func fun1(a: Int,_ b: Int) -> Int {
return a + b
}
func fun2() {
}
fun1(1,2)
fun2()
上面的两个函数的类型分别是: 使用函数类型在Swift中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将适当的函数赋值给它。那么就可以使用这个常量或变量调用被赋值的函数。有相同匹配类型的不同函数可以被赋值给同一个变量,就像非函数类型的变量一样。像其他类型一样,当赋值一个函数给常量或变量时,你可以让 Swift 来推断其函数类型,而不用先声明其类型。 func fun1(a: Int,_ b: Int) -> Int {
return a + b
}
func fun2(a: Int,_ b: Int) -> Int {
return a - b
}
var a: (Int,Int) -> Int = fun1 // a和fun1具有相同的类型,这样的赋值是允许的
print(a) // (Function)
print(a(1,2)) // 调用被赋值的函数
a = fun2
print(a(1,2)) // 调用新的被赋值的函数
let b = fun2 // 直接赋值,不用先声明函数的类型
print(b(2,1))
函数类型作为参数类型可以把函数类型作为另一个函数的参数类型。这样就可以将函数的一部分实现留给函数的调用者来提供。 func fun1(a: Int,_ b: Int) -> Int {
return a + b
}
func fun2(f: (Int,Int) -> Int,a: Int,b: Int) { // 文档中在a和b之前都加了_ print(f(a,b)) } fun2(fun1,a: 1,b: 2)
在上面的代码中, 函数类型作为返回类型可以用函数类型作为另一个函数的返回类型。 func addOne(data: Int) -> Int {
return data + 1
}
func minusOne(data: Int) -> Int {
return data - 1
}
func fun(flag: Bool) -> (Int) -> Int {
if flag {
return addOne
} else {
return minusOne
}
}
var a = -2
print(fun(a < 0)(a)) // -1
嵌套函数前面看到的函数都叫 默认情况下,嵌套函数是对外界不可见的,但是可以被它们的外围函数(enclosing function)调用。一个外围函数也可以返回它的某一个嵌套函数,使得这个函数可以在其他域中被使用。 func fun(flag: Bool) -> (Int) -> Int {
func addOne(data: Int) -> Int {
return data + 1
}
func minusOne(data: Int) -> Int {
return data - 1
}
if flag {
return addOne
} else {
return minusOne
}
}
var a = -2
print(fun(a < 0)(a)) // -1,一个外围函数也可以返回它的某一个嵌套函数,使得这个函数可以在其他域中被使用
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |