Swift中的函數

1. 函數的參數與返回值

1.1 多重返回值函數

你可以用元組(tuple)類型讓多個值作為一個復合值從函數中返 回。

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"

1.2 可選元組返回類型

如果函數返回的元組類型有可能整個元組都“沒有值”,你可以使用可選的(optional)元組返回類型反映整個元組可以是nil的事實。

注意:
可選元組類型如(Int, Int)?與元組包含的可選類型如(Int?, Int?)是不同的。可選的元祖類型,整個元組是可選的,而不只是元組中的每個元素值。

前面的minMax(array:)函數沒有對傳入的數組進行任何安全檢查,如果array是個空數組,會觸發一個運行時錯誤,使用可選元組返回類型,可以安全地處理這個問題。

func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty {
        return nil
    }
    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)
}

你可以使用可選綁定來檢查minMax(array:)函數返回的是一個存在的元組還是nil

if 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"

2.函數參數標簽和參數名稱

2.1 指定參數標簽

func greet(person: String, from hometown: String) -> String {
    return "Hello \(person)! Glad you could visit from \(hometown)"
}

from就是參數標簽,hometown則是參數名稱。

如果你希望忽略某個參數標簽,可以使用_來代替一個標簽。

2.2 默認參數值

func greet(person: String, from hometown: String = "Dream") -> String {
    return "Hello \(person)! Glad you could visit from \(hometown)"
}

greet(person: "John")

// 輸出 "Hello John! Glad you could visit from Dream"

2.3 可變參數

一個可變參數可以接受零個或多個值,通過在變量類型名后面加入(...)的方式來定義可變參數。

可變參數的傳入值在函數體中變為此類型的一個數組。

下面這個函數用來計算一組任意長度數字的算術平均數:

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)
// 返回 3.0

注意:
一個函數最多只能擁有一個可變參數

2.4 輸入輸出參數

函數參數默認是常量,試圖在函數體中更改參數值將會導致編譯錯誤。如果你想要一個函數可以修改參數的值,并且想要在這些修改在函數調用結束后仍然存在,那么就應該把這個參數定義為輸入輸出參數。

定義一個輸入輸出參數時,在參數定義前加inout關鍵字。一個輸入輸出參數有傳入函數的值,這個值被函數修改,然后被傳出函數,替換原來的值。

你只能傳遞變量給輸入輸出參數,常量或者字面量是不能被修改的。當傳入的參數作為輸入輸出參數時,需要在參數名前加&符,表示這個值可以被函數修改。

注意:
輸入輸出參數不能有默認值,而且可變參數不能用inout標記。

func swapTowInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTowInts(&someInt, &anotherInt)
print("someInt is now \(someInt), anotherInt is now \(anotherInt)")

// 輸出 "someInt is now 107, anotherInt is now 3\n"

注意:
輸入輸出參數和返回值是不一樣的。上面的swapTwoInts函數并沒有定義任何返回值,但是仍然修改了someIntanotherInt的值。輸入輸出參數是函數對函數體外產生影響的另一種方式。

3.函數類型

每個函數都有特定的函數類型,函數的類型由函數的參數類型和返回類型組成。

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

func multipyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

上面這兩個函數的類型是(Int, Int) -> Int,可以解讀為“這個函數類型有兩個Int型參數并返回一個Int型的值”。

func printHelloWordl() {
    print("Hello world!")
}

上面這個函數的類型是:() -> Void,或者叫做“沒有參數,并返回Void類型的函數“。

3.1 使用函數類型

在Swift中,使用函數類型就像使用其他類型一樣。例如,你可以定義一個類型為函數的常量或變量,并將適當的函數賦值給它:

var mathFunction:(Int ,Int) -> Int = addTwoInts

這段代碼可以被解讀為:“定義一個叫做mathFunciton的變量,類型是‘一個有兩個Int型的參數并返回一個Int型的值的函數‘,并讓這個新變量指向addTwoInts函數”。

print("Result: \(mathFunction(2, 3))")
// 輸出 "Result: 5\n"

有相同匹配類型的不同函數可以被賦值給同一個變量:

mathFunction = multipyTwoInts
print("Result: \(mathFunction(2, 3))")
// 輸出 "Result: 6\n"

就像其他類型一樣,當賦值一個函數給常量或變量時,你可以讓Swift來推斷其函數類型:

let anotherMathFunction = addTwoInts
print("\(anotherMathFunction(1, 2))")
// 輸出 "3\n"

3.2 函數類型作為參數類型

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}

printMathResult(addTwoInts, 3, 5)
// 打印 "Result: 8\n"

3.3 函數類型作為返回類型

func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 現在指向 stepBackward()

print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}

print("zero")

// 3...
// 2...
// 1...
// zero!

3.4 嵌套函數

目前為止你見到的所有函數都是全局函數,你也可以把函數定義在別的函數體中,稱作嵌套函數。

默認情況下,嵌套函數對外是不可見的,但是可以被它們的外圍函數調用。一個外圍函數也可以返回它的某一個嵌套函數,使得這個函數可以在其他域中被使用。

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backward ? stepBackward : stepForward
}

var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)

while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容