Swift 3.0之六、函數(shù)

函數(shù)是一個獨立的代碼塊瞄摊,用來執(zhí)行特定的任務(wù)勋又。

1. 定義和調(diào)用函數(shù)

Swift 函數(shù)一般形式為:

func 函數(shù)名:(形式參數(shù)1: 類型, 形式參數(shù)2: 類型, ...) -> 返回類型 {
    // 此函數(shù)要做的事兒
    return 返回類型
}

舉個栗子:

func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
}

函數(shù)調(diào)用形式為:
函數(shù)名(實際參數(shù)1,實際參數(shù)2换帜,...)楔壤,實際參數(shù)要和形式參數(shù)的順序和類型一致。
舉個?? :

func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))
// 結(jié)果為: "Hello again, Anna!"

2. 函數(shù)的形式參數(shù)和返回值

無形式參數(shù)的函數(shù)

func sayHelloWorld() -> String {  // 函數(shù)名后的括號不可省略
    return "hello, world"
}
print(sayHelloWorld())
// 結(jié)果為: "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))
// 結(jié)果為: "Hello again, Tim!"

無返回值的函數(shù)

// 嚴(yán)格意義上惯驼,無返回值的函數(shù)返回的是 Void 類型蹲嚣,即: "-> Void"
func greet(person: String) {  // "->" 和 "返回類型" 省略
    print("Hello, \(person)!")
}
greet(person: "Dave")
// 結(jié)果為: "Hello, Dave!"

有返回值的函數(shù)可以不使用其返回值,如下面的?? :

func printAndCount(string: String) -> Int {
    print(string)
    return string.characters.count
}
func printWithoutCounting(string: String) {
    let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// 結(jié)果為: "hello, world" 并且返回12
printWithoutCounting(string: "hello, world")
// 結(jié)果為: "hello, world" 但不返回值

返回值為元組的函數(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)
}

調(diào)用時:

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

返回值為可選元組的函數(shù)

// 在返回的元組括號后加上 "?" 就變?yōu)榭蛇x元組
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }  // 如果數(shù)組為空,返回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)
}

3.函數(shù)實際參數(shù)標(biāo)簽和形式參數(shù)名

  • 每一個函數(shù)的形式參數(shù)都包含: 實際參數(shù)標(biāo)簽和形式參數(shù)名议惰。
  • 實際參數(shù)標(biāo)簽用在調(diào)用函數(shù)的時候,形式參數(shù)名用在函數(shù)的實現(xiàn)當(dāng)中乡恕。
  • 默認(rèn)情況下言询,形式參數(shù)使用它們的形式參數(shù)名作為實際參數(shù)標(biāo)簽俯萎。

指定實際參數(shù)標(biāo)簽

通用格式為:

func 函數(shù)名(實際參數(shù)標(biāo)簽名 形式參數(shù)名: 參數(shù)類型) -> 返回類型{
    // 函數(shù)內(nèi)部使用形式參數(shù)名
    // 調(diào)用函數(shù)時使用實際參數(shù)標(biāo)簽名
}

舉個?? :

func greet(person: String, from hometown: String) -> String {
    return "Hello \(person)!  Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// 結(jié)果為: "Hello Bill!  Glad you could visit from Cupertino."

省略實際參數(shù)標(biāo)簽

如果不想使用實際參數(shù)標(biāo)簽的話,可以利用下劃線(_)代替运杭,如:

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
    // 
}
someFunction(1, secondParameterName: 2)

默認(rèn)形式參數(shù)值

形式參數(shù)參數(shù)類型后賦一個默認(rèn)值夫啊。
如果定義了默認(rèn)值,調(diào)用函數(shù)時可以省略這個形式參數(shù)辆憔,舉個?? :

func someFunction(parameterWithDefault: Int = 12) {
    print(parameterWithDefault)
}
someFunction(parameterWithDefault: 6) // parameterWithDefault 為 6
someFunction()  // parameterWithDefault 此時為默認(rèn)值 12

可變形式參數(shù)

一個可變形式參數(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)
// 返回5個數(shù)字的平均數(shù) 3.0
arithmeticMean(3, 8.25, 18.75)
// 返回3個數(shù)字的平均數(shù) 10.0

注意: 一個函數(shù)最多只能有一個可變形式參數(shù)

輸入輸出形式參數(shù)

  • 如果想讓函數(shù)能夠修改一個形式參數(shù)的值并在函數(shù)結(jié)束之后依然生效虱咧,那么就需要將形式參數(shù)定義為輸入輸出形式參數(shù)熊榛。
  • 在形式參數(shù)類型前添加inout關(guān)鍵字定義一個輸入輸出形式參數(shù)。
  • 只能把變量作為輸入輸出形式參數(shù)的實際參數(shù)彤钟,因為常量和字面量不能修改来候。
  • 函數(shù)調(diào)用時,在變量前邊添加一個和符合(&)來明確可以被函數(shù)修改逸雹。

輸入輸出形式參數(shù)不能有默認(rèn)值营搅,可變形式參數(shù)不能標(biāo)記為inout

舉個交換兩個變量值的?? :

// 定義函數(shù)
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

// 調(diào)用函數(shù):
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)  // 記得添加和符號 "&"
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// 結(jié)果為: "someInt is now 107, and anotherInt is now 3"

4. 函數(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ù)都是(Int, Int) -> Int,讀作”形參為兩個Int類型帖世,并返回一個Int類型值的類型“休蟹。
下面這個函數(shù)的類型則為() -> Void,或者“一個沒有形式參數(shù)的函數(shù)日矫,返回Void”:

func printHelloWorld() {
    print("hello, world")
}

使用函數(shù)類型

可以像使用Swift中的其他類型一樣使用函數(shù)類型赂弓,給一個常量或變量定義一個函數(shù)類型,并為其指定一個相應(yīng)的函數(shù)哪轿,如:

var mathFunction: (Int, Int) -> Int = addTwoInts
// 讀作: ”定義一個叫做mathFunction的變量盈魁,
// 它的類型是‘一個能接受兩 Int 值的函數(shù),并返回一個 Int 值’窃诉,
// 將這個變量指向 addTwoInts 函數(shù)“杨耙。

現(xiàn)在,可以用mathFunction這個變量調(diào)用函數(shù)飘痛,如:

print("Result: \(mathFunction(2, 3))")
// 結(jié)果為: "Result: 5"

當(dāng)然珊膜,也可以將變量指向別的同類型的函數(shù),如:

mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// 結(jié)果為: "Result: 6"

未給出常量或者變量類型時宣脉,編譯器會對類型進(jìn)行推斷:

let anotherMathFunction = addTwoInts
// anotherMathFunction 被推斷為 (Int, Int) -> Int 類型

函數(shù)類型作為形式參數(shù)類型

直接上?? :

// 第一個參數(shù)為“形參為兩個整型返回值為一個整型值”的函數(shù)類型
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// 結(jié)果為: "Result: 8"

函數(shù)類型作為返回類型

舉個?? :

// 先定義兩個(Int) -> Int 類型的函數(shù)车柠,
// 一個作用是返回比傳入數(shù)值大1的數(shù)字 另一個作用是返回比傳入數(shù)值小1的數(shù)字 
func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}

// 此函數(shù)的類型為 Bool -> (Int) -> Int
// 其參數(shù)為一個Bool值,返回值是(Int) -> Int函數(shù)類型
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    return backwards ? stepBackward : stepForward
}

// 使用chooseStepFunction函數(shù),返回需要的函數(shù)
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 現(xiàn)在指向 stepBackward() 函數(shù)

// 接下來竹祷,使 currentValue 變量一步步接近 0
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

5. 內(nèi)嵌函數(shù)

  • 上面所有函數(shù)都是在全局的范圍內(nèi)進(jìn)行定義的介蛉,我們也可以在函數(shù)的內(nèi)部定義另外的函數(shù),這就是內(nèi)嵌函數(shù)溶褪。

  • A函數(shù)的內(nèi)嵌函數(shù)B在A函數(shù)外部不可訪問,但可以通過A函數(shù)來返回B函數(shù)践险。

重寫上邊的?? 中的chooseStepFunction(backward:)來使用和返回內(nèi)嵌函數(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 現(xiàn)在指向 stepForward() 函數(shù)
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猿妈,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子巍虫,更是在濱河造成了極大的恐慌彭则,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件占遥,死亡現(xiàn)場離奇詭異俯抖,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瓦胎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門芬萍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人搔啊,你說我怎么就攤上這事柬祠。” “怎么了负芋?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵漫蛔,是天一觀的道長。 經(jīng)常有香客問我旧蛾,道長莽龟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任锨天,我火速辦了婚禮毯盈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绍绘。我一直安慰自己奶镶,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布陪拘。 她就那樣靜靜地躺著厂镇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪左刽。 梳的紋絲不亂的頭發(fā)上捺信,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼迄靠。 笑死秒咨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的掌挚。 我是一名探鬼主播雨席,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吠式!你這毒婦竟也來了陡厘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤特占,失蹤者是張志新(化名)和其女友劉穎糙置,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體是目,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡择示,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年殃恒,在試婚紗的時候發(fā)現(xiàn)自己被綠了伶跷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熏兄。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嗤疯,靈堂內(nèi)的尸體忽然破棺而出功舀,到底是詐尸還是另有隱情,我是刑警寧澤身弊,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布辟汰,位于F島的核電站,受9級特大地震影響阱佛,放射性物質(zhì)發(fā)生泄漏帖汞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一凑术、第九天 我趴在偏房一處隱蔽的房頂上張望翩蘸。 院中可真熱鬧,春花似錦淮逊、人聲如沸催首。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郎任。三九已至,卻和暖如春备籽,著一層夾襖步出監(jiān)牢的瞬間舶治,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留霉猛,地道東北人尺锚。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像惜浅,于是被迫代替她去往敵國和親瘫辩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容