Swift - 函数


函数

1 - 函数种类:有返回值带参、有返回值无参、无返回值带参、无返回值无参

 1 // 有返回值有参
 2 func greet(person: String, alreadyGreeted: Bool) -> String {
 3     
 4     if alreadyGreeted {
 5        // ...
 6     }else{
 7        // ...
 8     }
 9     
10     return "0"
11 }
12 print(greet(person: "Tim", alreadyGreeted: true))
13 
14 // 有返回值无参
15 func sayHelloWorld() -> String {
16     return "hello, world"
17 }
18 
19 // 无返回值带参
20 func greet(person: String) {
21     print("Hello, \(person)!")
22     
23     // 确切地说是返回一个 Void 型特殊值,它是一个空元组,写成 ()
24     return()
25 }

2 - 多重返回值函数

① 使用元组让多个值作为一个复合值从函数中返回

// 元组成员值已被命名,获取时可直接用检索找到的最小值与最大值
func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    
    // 使用索引寻找最大值/最小值
    return (currentMin, currentMax)
}

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)") // min is -6 and max is 109

② 可选元组返回类型:可选元组类型 (Int, Int)? 整个元组是可选的,不只是元组中的每个元素值;而元组包含可选类型 (Int?, Int?) 元组中的元素值是可选的

 1 // 前面的 minMax(array:) 函数不会对传入的数组执行任何安全检查
 2 // 如果 array 参数是一个空数组,那么在访问 array[0] 时会报错
 3 // 为了安全地处理空数组问题,可以使用可选元组返回类型
 4 func minMax02(array: [Int]) -> (min: Int, max: Int)? {
 5     
 6     if array.isEmpty {
 7         return nil
 8     }
 9     
10     var currentMin = array[0]
11     var currentMax = array[0]
12     
13     for value in array[1..<array.count] {
14         if value < currentMin {
15             currentMin = value
16         } else if value > currentMax {
17             currentMax = value
18         }
19     }
20     return (currentMin, currentMax)
21 }

3 - 隐式返回的函数:如果整个函数体是一个单行表达式,那么这个函数就可以隐式地返回这个表达式

// 标准
func anotherGreeting(eachPerson: String) -> String {
    return "Hello, " + eachPerson + "!"
}

// 隐式
func greeting(everyPerson: String) -> String {
    "Hello, " + everyPerson + "!"
}

4 - 参数标签、参数名称

① 每个函数参数都有一个参数标签以及一个参数名称

 1 // firstParameterName 和 secondParameterName 均是参数
 2 func someFunction(firstParameterName: Int, secondParameterName: Int) {
 3     
 4 }
 5 someFunction(firstParameterName: 1, secondParameterName: 2)
 6 
 7 // 在参数名称前指定它的参数标签,中间以空格分隔
 8 func greet(person: String,  from hometown: String) -> String {
 9     return "Hello \(person)!  Glad you could visit from \(hometown)."
10 }
11 
12 // 参数标签的使用能够让一个函数在调用时更有表达力
13 print(greet(person: "Bill", from: "Cupertino"))// Hello Bill!  Glad you could visit from Cupertino.

② 忽略参数标签:如果你不希望为某个参数添加一个标签,可以使用一个下划线 _ 来代替一个明确的参数标签

func someFunction02(_ firstParameterName: Int, secondParameterName: Int) {
     
}
// 编译通过
someFunction02(1, secondParameterName: 2)

someFunction02(1,2) // 编译报错
someFunction02(firstParameterName: 1,2) // 编译报错

③ 默认参数值:如果不传第二个参数,parameterWithDefault 会值为 12

func someFunction03(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    
}
someFunction03(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault = 6
someFunction03(parameterWithoutDefault: 4) // parameterWithDefault = 12

5 - 可变参数:可以接受零个或多个值,但是一个函数最多只能拥有一个可变参数。我们可以在变量类型名后面加入 ... 来定义可变参数

// 计算一组任意长度数字的算术平均数
func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)

6 - 输入输出参数

① 函数参数默认是常量,试图在函数体中更改参数值将会导致编译错误。如果你想要一个函数可以修改参数的值,那么就应该把这个参数定义为输入输出参数

② 在参数名前加 & 符,表示这个值可以被函数修改

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)

7 - 函数类型

① 你可以定义一个类型为函数的常量或变量,并将适当的函数赋值给它

// 函数类型是 (Int, Int) -> Int 型
func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}
// 函类类型变量
var mathFunction: (Int, Int) -> Int = addTwoInts
print("Result: \(mathFunction(2, 3))")  // Result: 5

// 同样完全可以让 Swift 来推断其函数类型
let anotherMathFunction = addTwoInts // anotherMathFunction 被推断为 (Int, Int) -> Int 类型

② 函数类型作为参数

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5) // Result: 8

③ 函数类型作为返回值 | 函数嵌套

 1 // 以下两个函数的类型都是 (Int) -> Int 型
 2 func stepForward(_ input: Int) -> Int {
 3     return input + 1
 4 }
 5 func stepBackward(_ input: Int) -> Int {
 6     return input - 1
 7 }
 8 
 9 // 根据布尔值 backwards 来返回 stepForward(_:) 函数 或 stepBackward(_:) 函数
10 func chooseStepFunction(backward: Bool) -> (Int) -> Int {
11     return backward ? stepBackward : stepForward
12 }
13 var currentValue = 3
14 let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
15 
16 // 趋近于 0
17 while currentValue != 0 {
18     print("\(currentValue)... ")
19     currentValue = moveNearerToZero(currentValue)
20 }
21 print("zero!")
22 
23 // 嵌套:默认情况下嵌套函数是对外界不可见的,但是可以被它们的外围函数调用
24 // 一个外围函数也可以返回它的某一个嵌套函数
25 func chooseStepFunctionAgain(backward: Bool) -> (Int) -> Int {
26     
27     func stepForward(input: Int) -> Int {
28         return input + 1
29     }
30     
31     func stepBackward(input: Int) -> Int {
32         return input - 1
33     }
34     return backward ? stepBackward : stepForward
35 }
36 var currentNumber = -4
37 let moveToZero = chooseStepFunction(backward: currentNumber > 0)
38 while currentNumber != 0 {
39     
40     print("\(currentNumber)... ")
41     currentNumber = moveToZero(currentNumber)
42 }
43 print("zero!")