定義和調(diào)用函數(shù)
在下面的例子中的函數(shù)叫做greet(person :)耙旦,因為這是它的作用 - 它需要一個人的名字作為輸入碎罚,并返回一個問候語的人悬荣。 為了實現(xiàn)這一點骑冗,你定義一個輸入?yún)?shù) - 一個String值入撒,稱為person - 和一個String的返回類型隆豹,它將包含該人的問候語:
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
所有這些信息都匯總到函數(shù)的定義中,前綴是func關(guān)鍵字茅逮。 通過返回箭頭 - >(一個連字符后跟一個直角括號)來指示函數(shù)的返回類型璃赡,后面跟著要返回的類型的名稱。
該定義描述了函數(shù)的作用献雅,它期望接收的內(nèi)容碉考,以及它完成后返回的內(nèi)容。 該定義使得函數(shù)可以從代碼中的其他位置輕松調(diào)用:
print(greet(person: "Anna"))
// Prints "Hello, Anna!"
print(greet(person: "Brian"))
// Prints "Hello, Brian!"
要使此函數(shù)的主體更短挺身,可以將消息創(chuàng)建和return語句合并為一行:
func greetAgain(person: String) -> String {
return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))
// Prints "Hello again, Anna!"
函數(shù)參數(shù)和返回值
無參數(shù)的函數(shù)
func sayHelloWorld() -> String {
return "hello, world"
}
print(sayHelloWorld())
// Prints "hello, world"
多個參數(shù)的函數(shù)
func greet(person: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
return greetAgain(person: person)
} else {
return greet(person: person)
}
}
print(greet(person: "Tim", alreadyGreeted: true))
// Prints "Hello again, Tim!"
無返回值的函數(shù)
func greet(person: String) {
print("Hello, \(person)!")
}
greet(person: "Dave")
// Prints "Hello, Dave!"
因為它不需要返回值侯谁,所以函數(shù)的定義不包括返回箭頭( - >)或返回類型。
注意:
嚴格地說章钾,這個版本的greet(person :)函數(shù)仍然返回一個值墙贱,即使沒有定義返回值。 沒有定義的返回類型的函數(shù)返回類型為Void的特殊值贱傀。 這只是一個空的元組惨撇,它寫成()。
調(diào)用函數(shù)時窍箍,可以忽略函數(shù)的返回值:
func printAndCount(string: String) -> Int {
print(string)
return string.characters.count
}
func printWithoutCounting(string: String) {
let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting(string: "hello, world")
// prints "hello, world" but does not return a value
第一個函數(shù)printAndCount(string :)打印一個字符串串纺,然后將其字符計數(shù)作為Int返回丽旅。 第二個函數(shù)printWithoutCounting(string :)調(diào)用第一個函數(shù),但忽略它的返回值纺棺。 當(dāng)調(diào)用第二個函數(shù)時榄笙,消息仍由第一個函數(shù)打印,但不使用返回的值祷蝌。
具有多個返回值的函數(shù)
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)
}
因為元組的成員值被命名為函數(shù)的返回類型的一部分茅撞,所以可以使用點語法訪問它們以檢索最小和最大找到的值:
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// Prints "min is -6 and max is 109"
注意
元組的成員不需要在從函數(shù)返回元組的點處命名,因為它們的名稱已經(jīng)被指定為函數(shù)的返回類型的一部分巨朦。
可選元組返回類型
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 :)函數(shù)是否返回實際的元組值或nil:
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
// Prints "min is -6 and max is 109"
函數(shù)參數(shù)標簽和參數(shù)名稱
每個函數(shù)參數(shù)都具有參數(shù)標簽和參數(shù)名稱米丘。 參數(shù)標簽在調(diào)用函數(shù)時使用; 每個參數(shù)寫在函數(shù)調(diào)用中,其參數(shù)標簽在它之前糊啡。 參數(shù)名稱用于函數(shù)的實現(xiàn)拄查。 默認情況下,參數(shù)使用其參數(shù)名稱作為其參數(shù)標簽棚蓄。
func someFunction(firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(firstParameterName: 1, secondParameterName: 2)
所有參數(shù)必須具有唯一的名稱堕扶。 盡管多個參數(shù)可能具有相同的參數(shù)標簽,但唯一的參數(shù)標簽有助于使代碼更具可讀性梭依。
指定參數(shù)標簽
您在參數(shù)名稱之前寫入?yún)?shù)標簽稍算,用空格分隔:
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
這里有一個greet(person :)函數(shù)的變體,它使用一個人的姓名和家鄉(xiāng)并返回問候語:
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Prints "Hello Bill! Glad you could visit from Cupertino."
省略參數(shù)標簽
如果不想要參數(shù)的參數(shù)標簽役拴,請為該參數(shù)編寫下劃線(_)糊探,而不是顯式參數(shù)標簽。
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(1, secondParameterName: 2)
注意:
如果參數(shù)具有參數(shù)標簽河闰,則在調(diào)用函數(shù)時必須標記參數(shù)科平。
默認參數(shù)值
您可以通過為該參數(shù)的類型之后的參數(shù)分配值來為該函數(shù)中的任何參數(shù)定義默認值。 如果定義了默認值淤击,則可以在調(diào)用該函數(shù)時忽略該參數(shù)匠抗。
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
// If you omit the second argument when calling this function, then
// the value of parameterWithDefault is 12 inside the function body.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12
將沒有默認值的參數(shù)放在函數(shù)的參數(shù)列表的開頭故源,在具有默認值的參數(shù)之前污抬。 沒有默認值的參數(shù)通常對函數(shù)的意義更重要。
變量參數(shù)
傳遞給可變參數(shù)的值在函數(shù)體內(nèi)作為適當(dāng)類型的數(shù)組使用绳军。 例如印机,具有數(shù)字名稱和Double ...類型的可變參數(shù)在函數(shù)體內(nèi)作為稱為[Double]類型的常數(shù)數(shù)組。下面的示例計算任何長度的數(shù)字列表的算術(shù)平均值(也稱為平均值):
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)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
輸入 - 輸出參數(shù)
默認情況下门驾,函數(shù)參數(shù)是常量射赛。試圖從函數(shù)體內(nèi)更改函數(shù)參數(shù)的值會導(dǎo)致編譯時錯誤。這意味著您不能錯誤地更改參數(shù)的值奶是。如果希望函數(shù)修改參數(shù)的值楣责,并且希望這些更改在函數(shù)調(diào)用結(jié)束后保留??竣灌,請將該參數(shù)定義為in-out參數(shù)。
您通過將inout參數(shù)放在參數(shù)類型之前來編寫in-out參數(shù)秆麸。輸入 - 輸出參數(shù)具有傳遞到函數(shù)的值初嘹,由函數(shù)修改,并被傳回函數(shù)以替換原始值沮趣。有關(guān)輸入?yún)?shù)和關(guān)聯(lián)編譯器優(yōu)化行為的詳細討論屯烦,請參閱輸入?yún)?shù)。
您只能將一個變量作為in-out參數(shù)的參數(shù)傳遞房铭。您不能將常量或字面值作為參數(shù)傳遞驻龟,因為常量和字面值不能修改。在將變量的名稱作為參數(shù)傳遞給in-out參數(shù)時缸匪,在變量名稱前放置一個&符號(&)翁狐,以指示它可以由函數(shù)修改。
注意:
輸入 - 輸出參數(shù)不能具有默認值凌蔬,并且可變參數(shù)不能標記為輸入谴蔑。
下面是一個名為swapTwoInts(: :)的函數(shù)的示例,它有兩個in-out整數(shù)參數(shù)a和b:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
swapTwoInts(: :)函數(shù)只是將b的值轉(zhuǎn)換為a龟梦,將a的值轉(zhuǎn)換為b隐锭。 該函數(shù)通過將a的值存儲在名為temporaryA的臨時常量中,將b的值分配給a计贰,然后將temporaryA分配給b來執(zhí)行此交換钦睡。
您可以調(diào)用具有兩個Int類型變量的swapTwoInts(: :)函數(shù)來交換它們的值。 請注意躁倒,someInt和anotherInt的名稱在傳遞給swapTwoInts(: :)函數(shù)時荞怒,以&符號作為前綴:
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3"
上面的示例顯示,someInt和anotherInt的原始值由swapTwoInts(: :)函數(shù)修改秧秉,即使它們最初在函數(shù)之外定義褐桌。
輸入 - 輸出參數(shù)與函數(shù)返回值不同。 上面的swapTwoInts示例沒有定義返回類型或返回值象迎,但它仍然修改someInt和anotherInt的值荧嵌。 輸入 - 輸出參數(shù)是函數(shù)具有超出函數(shù)體范圍的效果的替代方法。
函數(shù)類型
每個函數(shù)都有一個特定的函數(shù)類型砾淌,由參數(shù)類型和函數(shù)的返回類型組成啦撮。
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
此示例定義了兩個簡單的數(shù)學(xué)函數(shù),稱為addTwoInts和multiplyTwoInts汪厨。 這些函數(shù)各取兩個Int值赃春,并返回一個Int值。
你在Swift中使用類似任何其他類型的函數(shù)類型劫乱。 例如织中,您可以將常量或變量定義為函數(shù)類型锥涕,并為該變量分配適當(dāng)?shù)暮瘮?shù):
var mathFunction: (Int, Int) -> Int = addTwoInts
這可以看作:
“定義一個名為mathFunction的變量,它的類型是一個函數(shù)狭吼,它接受兩個Int值站楚,并返回一個Int值。設(shè)置這個新變量以引用稱為addTwoInts的函數(shù)搏嗡。
addTwoInts(: :)函數(shù)與mathFunction變量具有相同的類型窿春,因此Swift的類型檢查器允許此賦值。現(xiàn)在可以調(diào)用名為mathFunction的已分配函數(shù):
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5"
與任何其他類型一樣采盒,當(dāng)您將函數(shù)分配給常量或變量時旧乞,您可以將其留給Swift來推斷函數(shù)類型:
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int
函數(shù)作為參數(shù)
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Prints "Result: 8"
函數(shù)作為返回值
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
這里有一個名為chooseStepFunction(backward :)的函數(shù),它的返回類型是(Int) - > Int磅氨。 chooseStepFunction(backward :)函數(shù)基于一個名為backward的布爾參數(shù)返回stepForward(_ :)函數(shù)或stepBackward(_ :)函數(shù):
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward
}
你現(xiàn)在可以使用chooseStepFunction(backward :)來獲取一個方向或另一個方向的函數(shù):
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!
嵌套函數(shù)
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)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!