> 1.0 翻譯:[honghaoz](https://github.com/honghaoz)?校對:[LunaticM](https://github.com/LunaticM)
>
> 2.0 翻譯+校對:[dreamkidd](https://github.com/dreamkidd)
本頁包含內容:
[TOC=2]
函數是用來完成特定任務的獨立的代碼塊。你給一個函數起一個合適的名字,用來標識函數做什么,并且當函數需要執行的時候,這個名字會被“調用”。
Swift 統一的函數語法足夠靈活,可以用來表示任何函數,包括從最簡單的沒有參數名字的 C 風格函數,到復雜的帶局部和外部參數名的 Objective-C 風格函數。參數可以提供默認值,以簡化函數調用。參數也可以既當做傳入參數,也當做傳出參數,也就是說,一旦函數執行結束,傳入的參數值可以被修改。
在 Swift 中,每個函數都有一種類型,包括函數的參數值類型和返回值類型。你可以把函數類型當做任何其他普通變量類型一樣處理,這樣就可以更簡單地把函數當做別的函數的參數,也可以從其他函數中返回函數。函數的定義可以寫在在其他函數定義中,這樣可以在嵌套函數范圍內實現功能封裝。
## 函數的定義與調用(Defining and Calling Functions)
當你定義一個函數時,你可以定義一個或多個有名字和類型的值,作為函數的輸入(稱為參數,parameters),也可以定義某種類型的值作為函數執行結束的輸出(稱為返回類型)。
每個函數有個函數名,用來描述函數執行的任務。要使用一個函數時,你用函數名“調用”,并傳給它匹配的輸入值(稱作實參,arguments)。一個函數的實參必須與函數參數表里參數的順序一致。
在下面例子中的函數叫做`"sayHello(_:)"`,之所以叫這個名字,是因為這個函數用一個人的名字當做輸入,并返回給這個人的問候語。為了完成這個任務,你定義一個輸入參數-一個叫做?`personName`?的?`String`?值,和一個包含給這個人問候語的?`String`?類型的返回值:
~~~
func sayHello(personName: String) -> String {
let greeting = "Hello, " + personName + "!"
return greeting
}
~~~
所有的這些信息匯總起來成為函數的定義,并以?`func`?作為前綴。指定函數返回類型時,用返回箭頭?`->`(一個連字符后跟一個右尖括號)后跟返回類型的名稱的方式來表示。
該定義描述了函數做什么,它期望接收什么和執行結束時它返回的結果是什么。這樣的定義使得函數可以在別的地方以一種清晰的方式被調用:
~~~
print(sayHello("Anna"))
// prints "Hello, Anna!"
print(sayHello("Brian"))
// prints "Hello, Brian!"
~~~
調用?`sayHello(_:)`?函數時,在圓括號中傳給它一個?`String`?類型的實參。因為這個函數返回一個?`String`?類型的值,`sayHello`?可以被包含在?`print`?的調用中,用來輸出這個函數的返回值,正如上面所示。
在?`sayHello(_:)`?的函數體中,先定義了一個新的名為?`greeting`?的?`String`?常量,同時賦值了給?`personName`?的一個簡單問候消息。然后用?`return`?關鍵字把這個問候返回出去。一旦?`return greeting`?被調用,該函數結束它的執行并返回?`greeting`?的當前值。
你可以用不同的輸入值多次調用?`sayHello(_:)`。上面的例子展示的是用`"Anna"`和`"Brian"`調用的結果,該函數分別返回了不同的結果。
為了簡化這個函數的定義,可以將問候消息的創建和返回寫成一句:
~~~
func sayHelloAgain(personName: String) -> String {
return "Hello again, " + personName + "!"
}
print(sayHelloAgain("Anna"))
// prints "Hello again, Anna!"
~~~
## 函數參數與返回值(Function Parameters and Return Values)
函數參數與返回值在Swift中極為靈活。你可以定義任何類型的函數,包括從只帶一個未名參數的簡單函數到復雜的帶有表達性參數名和不同參數選項的復雜函數。
### 多重輸入參數(Multiple Input Parameters)
函數可以有多個輸入參數,寫在圓括號中,用逗號分隔。
下面這個函數用一個半開區間的開始點和結束點,計算出這個范圍內包含多少數字:
~~~
func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}
print(halfOpenRangeLength(1, 10))
// prints "9"
~~~
### 無參函數(Functions Without Parameters)
函數可以沒有參數。下面這個函數就是一個無參函數,當被調用時,它返回固定的?`String`?消息:
~~~
func sayHelloWorld() -> String {
return "hello, world"
}
print(sayHelloWorld())
// prints "hello, world"
~~~
盡管這個函數沒有參數,但是定義中在函數名后還是需要一對圓括號。當被調用時,也需要在函數名后寫一對圓括號。
### 多參量函數 (Functions With Multiple Parameters)
函數可以有多種輸入參數,這寫參數被包含在函數的括號之中,以逗號分隔.
這個函數取得一個人的名字和是否被招呼作為輸入,并對那個人返回適當地問候語:
~~~
func sayHello(personName: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
return sayHelloAgain(personName)
} else {
return sayHello(personName)
}
}
print(sayHello("Tim", alreadyGreeted: true))
// prints "Hello again, Tim!"
~~~
你通過在括號內傳遞一個`String`參數值和一個標識為`alreadyGreeted`的`Bool`值,使用逗號分隔來調用`sayHello(_:alreadyGreeted:)`函數.
當調用超過一個參數的函數時,第一個參數后的參數根據其對應的參數名稱標記,函數參數命名在[函數參數名稱(Function Parameter Names)](http://wiki.jikexueyuan.com/project/swift/chapter2/06_Functions.html#Function_Parameter_Names)有更詳細的描述.
### 無返回值函數(Functions Without Return Values)
函數可以沒有返回值。下面是?`sayHello(_:)`?函數的另一個版本,叫?`sayGoodbye(_:)`,這個函數直接輸出?`String`?值,而不是返回它:
~~~
func sayGoodbye(personName: String) {
print("Goodbye, \(personName)!")
}
sayGoodbye("Dave")
// prints "Goodbye, Dave!"
~~~
因為這個函數不需要返回值,所以這個函數的定義中沒有返回箭頭(->)和返回類型。
> 注意: 嚴格上來說,雖然沒有返回值被定義,`sayGoodbye(_:)`?函數依然返回了值。沒有定義返回類型的函數會返回特殊的值,叫?`Void`。它其實是一個空的元組(tuple),沒有任何元素,可以寫成`()`。
被調用時,一個函數的返回值可以被忽略:
~~~
func printAndCount(stringToPrint: String) -> Int {
print(stringToPrint)
return stringToPrint.characters.count
}
func printWithoutCounting(stringToPrint: String) {
printAndCount(stringToPrint)
}
printAndCount("hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting("hello, world")
// prints "hello, world" but does not return a value
~~~
第一個函數?`printAndCount(_:)`,輸出一個字符串并返回?`Int`?類型的字符數。第二個函數?`printWithoutCounting`調用了第一個函數,但是忽略了它的返回值。當第二個函數被調用時,消息依然會由第一個函數輸出,但是返回值不會被用到。
> 注意: 返回值可以被忽略,但定義了有返回值的函數必須返回一個值,如果在函數定義底部沒有返回任何值,并且試圖這樣做,這將導致編譯錯誤(compile-time error)。
### 多重返回值函數(Functions with Multiple Return Values)
你可以用元組(tuple)類型讓多個值作為一個復合值從函數中返回。
下面的這個例子中,定義了一個名為`minMax(_:)`的函數,作用是在一個`Int`數組中找出最小值與最大值.
~~~
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)
}
~~~
`minMax(_:)`函數返回一個包含兩個`Int`值的元組,這些值被標記為`min`和`max`,一遍查詢函數的返回值時他們可以被訪問.
`minMax(_:)`的函數體中,在開始的時候設置兩個工作變量`currentMin`和`currentMax`作為數組中的第一個`Int`值.然后函數會遍歷數組中剩余的值并檢查該值是否比`currentMin`和`currentMax`更小或更大.最后數組中的最小值與最大值返回兩個`Int`值最為一個元組.
因為元組的成員值被命名為函數的返回類型的一部分??,可以通過點語法來訪問與取回發現的最小值與最小值:
~~~
let bounds = minMax([8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// prints "min is -6 and max is 109"
~~~
需要注意的是,元組的成員不需要在函數中返回時命名,因為它們的名字已經在函數返回類型中有了定義。
可選元組返回類型(Optional Tuple Return Types)
如果函數返回的元組類型中有可能在整個元組中含有“沒有值”,你可以使用_可選的(Optional)_?元組返回類型反映整個元組可以是`nil`的事實.你可以通過在元組類型的右括號后放置一個問號來定義一個可選元組,例如`(Int,Int)?`或`(String,Int,Bool)?`
> 注意: 可選元組類型如`(Int,Int)?`與元組包含可選屬性如`(Int?,Int?)`是不同的.可選的元組類型,整個數組是可選的,而不只是元組中的每個元素值.
前面的`minMax(_:)`函數返回了一個包含兩個`Int`值的元組.但是函數不會在數組中執行任何安全檢查,如果`array`參數有一個空數組,如上定義的`minMax(_:)`在試圖訪問`array[0]`時會觸發一個運行時錯誤.
為了安全的處理這個"空數組"問題,寫一個`minMax(_:)`函數使用可選元組返回類型,并且當數組為空時返回`nil`:
~~~
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(_:)`函數返回的是一個實際的元組值還是`nil`
~~~
if let bounds = minMax([8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
// prints "min is -6 and max is 109"
~~~
## 函數參數名稱(Function Parameter Names)
函數參數都有一個_外部參數名(external parameter name)_和一個_本地參數名(local parameter name)_.外部參數名用來標記傳遞給函數調用的參數,本地參數名在實現函數的時候使用.
~~~
func someFunction(firstParameterName: Int, secondParameterName: Int) {
// function body goes here
// firstParameterName and secondParameterName refer to
// the argument values for the first and second parameters
}
someFunction(1, secondParameterName: 2)
~~~
一般情況下,第一個參數省略其外部參數名,第二個以后的參數使用其本地參數名作為自己的外部參數名.所有參數需要有不同的本地參數名,但可以共享相同的外部參數名.
### 指定外部參數名(Specifying External Parameter Names)
你可以在本地參數名前指定外部參數名,中間以空格分隔.
~~~
func someFunction(externalParameterName localParameterName: Int) {
// function body goes here, and can use localParameterName
// to refer to the argument value for that parameter
}
~~~
> 注意: 如果你提供了外部參數名,那么函數在被調用時,必須使用外部參數名。
這個版本的`sayHello(_:)`函數,得到了兩個人的名字,會同時返回對他倆的問候:
~~~
func sayHello(to person: String, and anotherPerson: String) -> String {
return "Hello \(person) and \(anotherPerson)!"
}
print(sayHello(to: "Bill", and: "Ted"))
// prints "Hello Bill and Ted!"
~~~
為每個參數指定外部參數名,在你調用函數`sayHello(to:and:)`函數時時兩個參數都必須被標記出來.
使用外部函數名可以使得函數可以用一句話表達清楚,并且使得函數體內部可讀,能表達出函數的明確意圖.
### 忽略外部參數名(Omitting External Parameter Names)
如果你不想為第二個及后續的參數設置參數名,用一個下劃線(_)代替一個明確地參數名.
~~~
func someFunction(firstParameterName: Int, _ secondParameterName: Int) {
// function body goes here
// firstParameterName and secondParameterName refer to
// the argument values for the first and second parameters
}
someFunction(1, 2)
~~~
> 注意: 因為第一個參數默認忽略其外部參數名稱,明確寫下劃線是多余的。
### 默認參數值(Default Parameter Values)
你可以在函數體中為每個參數定義`默認值(Deafult Values)`。當默認值被定義后,調用這個函數時可以忽略這個參數。
~~~
func someFunction(parameterWithDefault: Int = 12) {
// function body goes here
// if no arguments are passed to the function call,
// value of parameterWithDefault is 42
}
someFunction(6) // parameterWithDefault is 6
someFunction() // parameterWithDefault is 12
~~~
> 注意: 將帶有默認值的參數放在函數參數列表的最后。這樣可以保證在函數調用時,非默認參數的順序是一致的,同時使得相同的函數在不同情況下調用時顯得更為清晰。
### 可變參數(Variadic Parameters)
一個`可變參數(variadic parameter)`可以接受零個或多個值。函數調用時,你可以用可變參數來傳入不確定數量的輸入參數。通過在變量類型名后面加入`(...)`的方式來定義可變參數。
傳入可變參數的值在函數體內當做這個類型的一個數組。例如,一個叫做?`numbers`?的?`Double...`?型可變參數,在函數體內可以當做一個叫?`numbers`?的?`Double[]`?型的數組常量。
下面的這個函數用來計算一組任意長度數字的`算術平均數(arithmetic mean)`:
~~~
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
~~~
> 注意: 最多可以有一個可變參數函數,和它必須出現在參數列表中,為了避免歧義在調用函數有多個參數。 如果你的函數有一個或多個參數有默認值,還有一個可變的參數,將可變參寫在參數列表的最后。
如果函數有一個或多個帶默認值的參數,而且還有一個可變參數,那么把可變參數放在參數表的最后。
### 常量參數和變量參數(Constant and Variable Parameters)
函數參數默認是常量。試圖在函數體中更改參數值將會導致編譯錯誤。這意味著你不能錯誤地更改參數值。
但是,有時候,如果函數中有傳入參數的變量值副本將是很有用的。你可以通過指定一個或多個參數為變量參數,從而避免自己在函數中定義新的變量。變量參數不是常量,你可以在函數中把它當做新的可修改副本來使用。
通過在參數名前加關鍵字?`var`?來定義變量參數:
~~~
func alignRight(var string: String, totalLength: Int, pad: Character) -> String {
let amountToPad = totalLength - string.characters.count
if amountToPad < 1 {
return string
}
let padString = String(pad)
for _ in 1...amountToPad {
string = padString + string
}
return string
}
let originalString = "hello"
let paddedString = alignRight(originalString, totalLength: 10, pad: "-")
// paddedString is equal to "-----hello"
// originalString is still equal to "hello"
~~~
這個例子中定義了一個新的叫做?`alignRight(_:totalLength:pad:)`?的函數,用來右對齊輸入的字符串到一個長的輸出字符串中。左側空余的地方用指定的填充字符填充。這個例子中,字符串`"hello"`被轉換成了`"-----hello"`。
`alignRight(_:totalLength:pad:)`?函數將參數?`string`?定義為變量參數。這意味著?`string`?現在可以作為一個局部變量,用傳入的字符串值初始化,并且可以在函數體中進行操作。
函數首先找出有多少字符需要被添加到左邊的字符串以右對齊在整個字符串。這個值是存儲在一個本地常數稱為amountToPad。如果不需要填充(也就是說,如果amountToPad小于1),該函數返回字符串沒有填充的輸入值。 否則,該函數創建一個新的臨時字符串常量稱為padString,初始化填充字符,并將amountToPad padString副本添加到現有的左邊的字符串。(一個字符串值不能被添加到一個字符值,所以padString常數用于確保雙方+操作符的字符串值)。
該函數首先計算出多少個字符需要被添加到?`string`?的左邊,以右對齊到總的字符串中。這個值存在局部常量`amountToPad`?中。如果不需要填充(即,如果`amountToPad`小于`1`),該函數返回沒有填充輸入的`string`.
否則,該函數會建立一個臨時的String常量稱為`padString`,初始化`pad`字符,并將`amountToPad`作為`padString`的副本添加到現有的字符串左邊.(一個`Character`后不能直接添加一個`String`值,所以`padString`經常用于確保`+`號兩邊都是`String`值.)
> 注意: 對變量參數所進行的修改在函數調用結束后便消失了,并且對于函數體外是不可見的。變量參數僅僅存在于函數調用的生命周期中。
### 輸入輸出參數(In-Out Parameters)
變量參數,正如上面所述,僅僅能在函數體內被更改。如果你想要一個函數可以修改參數的值,并且想要在這些修改在函數調用結束后仍然存在,那么就應該把這個參數定義為輸入輸出參數(In-Out Parameters)。
定義一個輸入輸出參數時,在參數定義前加?`inout`?關鍵字。一個輸入輸出參數有傳入函數的值,這個值被函數修改,然后被傳出函數,替換原來的值。
你只能將變量作為輸入輸出參數。你不能傳入常量或者字面量(literal value),因為這些量是不能被修改的。當傳入的參數作為輸入輸出參數時,需要在參數前加`&`符,表示這個值可以被函數修改。
> 注意: 輸入輸出參數不能有默認值,而且可變參數不能用?`inout`?標記。如果你用?`inout`?標記一個參數,這個參數不能被?`var`?或者?`let`?標記。
下面是例子,`swapTwoInts(_:_:)`?函數,有兩個分別叫做?`a`?和?`b`?的輸入輸出參數:
~~~
func swapTwoInts(inout a: Int, inout _ b: Int) {
let temporaryA = a
a = b
b = temporaryA
}
~~~
這個?`swapTwoInts(_:_:)`?函數僅僅交換?`a`?與?`b`?的值。該函數先將?`a`?的值存到一個暫時常量?`temporaryA`?中,然后將`b`?的值賦給?`a`,最后將?`temporaryA`?幅值給?`b`。
你可以用兩個?`Int`?型的變量來調用?`swapTwoInts(_:_:)`。需要注意的是,`someInt`?和?`anotherInt`?在傳入`swapTwoInts(_:_:)`?函數前,都加了?`&`?的前綴:
~~~
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(_:_:)`?函數中被修改,盡管它們的定義在函數體外。
> 注意: 輸入輸出參數和返回值是不一樣的。上面的?`swapTwoInts`?函數并沒有定義任何返回值,但仍然修改了`someInt`?和?`anotherInt`?的值。輸入輸出參數是函數對函數體外產生影響的另一種方式。
## 函數類型(Function Types)
每個函數都有種特定的函數類型,由函數的參數類型和返回類型組成。
例如:
~~~
func addTwoInts(a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(a: Int, _ b: Int) -> Int {
return a * b
}
~~~
這個例子中定義了兩個簡單的數學函數:`addTwoInts`?和?`multiplyTwoInts`。這兩個函數都傳入兩個?`Int`?類型, 返回一個合適的`Int`值。
這兩個函數的類型是?`(Int, Int) -> Int`,可以讀作“這個函數類型,它有兩個?`Int`?型的參數并返回一個?`Int`?型的值。”。
下面是另一個例子,一個沒有參數,也沒有返回值的函數:
~~~
func printHelloWorld() {
print("hello, world")
}
~~~
這個函數的類型是:`() -> void`,或者叫“沒有參數,并返回?`Void`?類型的函數”。
### 使用函數類型(Using Function Types)
在 Swift 中,使用函數類型就像使用其他類型一樣。例如,你可以定義一個類型為函數的常量或變量,并將函數賦值給它:
~~~
var mathFunction: (Int, Int) -> Int = addTwoInts
~~~
這個可以讀作:
“定義一個叫做?`mathFunction`?的變量,類型是‘一個有兩個?`Int`?型的參數并返回一個?`Int`?型的值的函數’,并讓這個新變量指向?`addTwoInts`?函數”。
`addTwoInts`?和?`mathFunction`?有同樣的類型,所以這個賦值過程在 Swift 類型檢查中是允許的。
現在,你可以用?`mathFunction`?來調用被賦值的函數了:
~~~
print("Result: \(mathFunction(2, 3))")
// prints "Result: 5"
~~~
有相同匹配類型的不同函數可以被賦值給同一個變量,就像非函數類型的變量一樣:
~~~
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// prints "Result: 6"
~~~
就像其他類型一樣,當賦值一個函數給常量或變量時,你可以讓 Swift 來推斷其函數類型:
~~~
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int
~~~
### 函數類型作為參數類型(Function Types as Parameter Types)
你可以用`(Int, Int) -> Int`這樣的函數類型作為另一個函數的參數類型。這樣你可以將函數的一部分實現交由給函數的調用者。
下面是另一個例子,正如上面的函數一樣,同樣是輸出某種數學運算結果:
~~~
func printMathResult(mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8"
~~~
這個例子定義了?`printMathResult(_:_:_:)`?函數,它有三個參數:第一個參數叫?`mathFunction`,類型是`(Int, Int) -> Int`,你可以傳入任何這種類型的函數;第二個和第三個參數叫?`a`?和?`b`,它們的類型都是?`Int`,這兩個值作為已給的函數的輸入值。
當?`printMathResult(_:_:_:)`?被調用時,它被傳入?`addTwoInts`?函數和整數`3`和`5`。它用傳入`3`和`5`調用`addTwoInts`,并輸出結果:`8`。
`printMathResult(_:_:_:)`?函數的作用就是輸出另一個合適類型的數學函數的調用結果。它不關心傳入函數是如何實現的,它只關心這個傳入的函數類型是正確的。這使得?`printMathResult(_:_:_:)`?可以以一種類型安全(type-safe)的方式來保證傳入函數的調用是正確的。
### 函數類型作為返回類型(Function Type as Return Types)
你可以用函數類型作為另一個函數的返回類型。你需要做的是在返回箭頭(`->`)后寫一個完整的函數類型。
下面的這個例子中定義了兩個簡單函數,分別是?`stepForward`?和`stepBackward`。`stepForward`?函數返回一個比輸入值大一的值。`stepBackward`?函數返回一個比輸入值小一的值。這兩個函數的類型都是?`(Int) -> Int`:
~~~
func stepForward(input: Int) -> Int {
return input + 1
}
func stepBackward(input: Int) -> Int {
return input - 1
}
~~~
下面這個叫做?`chooseStepFunction(_:)`?的函數,它的返回類型是?`(Int) -> Int`?的函數。`chooseStepFunction(_:)`?根據布爾值?`backwards`?來返回?`stepForward(_:)`?函數或?`stepBackward(_:)`?函數:
~~~
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
return backwards ? stepBackward : stepForward
}
~~~
你現在可以用?`chooseStepFunction(_:)`?來獲得一個函數,不管是那個方向:
~~~
var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function
~~~
上面這個例子中計算出從?`currentValue`?逐漸接近到`0`是需要向正數走還是向負數走。`currentValue`?的初始值是`3`,這意味著?`currentValue > 0`?是真的(`true`),這將使得?`chooseStepFunction(_:)`?返回?`stepBackward(_:)`?函數。一個指向返回的函數的引用保存在了?`moveNearerToZero`?常量中。
現在,`moveNearerToZero`?指向了正確的函數,它可以被用來數到`0`:
~~~
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!
~~~
## 嵌套函數(Nested Functions)
這章中你所見到的所有函數都叫全局函數(global functions),它們定義在全局域中。你也可以把函數定義在別的函數體中,稱作嵌套函數(nested functions)。
默認情況下,嵌套函數是對外界不可見的,但是可以被他們封閉函數(enclosing function)來調用。一個封閉函數也可以返回它的某一個嵌套函數,使得這個函數可以在其他域中被使用。
你可以用返回嵌套函數的方式重寫?`chooseStepFunction(_:)`?函數:
~~~
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backwards ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(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!
~~~
- 介紹
- 歡迎使用 Swift
- 關于 Swift
- Swift 初見
- Swift 版本歷史記錄
- Swift1.0 發布內容
- Swift 教程
- 基礎部分
- 基本運算符
- 字符串和字符
- 集合類型
- 控制流
- 函數
- 閉包
- 枚舉
- 類和結構體
- 屬性
- 方法
- 下標腳本
- 繼承
- 構造過程
- 析構過程
- 自動引用計數
- 可選鏈
- 錯誤處理
- 類型轉換
- 嵌套類型
- 擴展
- 協議
- 泛型
- 權限控制
- 高級操作符
- 語言參考
- 關于語言參考
- 詞法結構
- 類型
- 表達式
- 語句
- 聲明
- 特性
- 模式
- 泛型參數
- 語法總結
- 蘋果官方Blog官方翻譯
- Access Control 權限控制的黑與白
- 造個類型不是夢-白話Swift類型創建
- WWDC里面的那個“大炮打氣球”
- Swift與C語言指針友好合作
- 引用類型和值類型的恩怨
- 訪問控制和Protected
- 可選類型完美解決占位問題