Day6 函數(shù)(Functions)

本頁包含內(nèi)容:
- 函數(shù)定義與調(diào)用
- 函數(shù)參數(shù)與返回值
- 函數(shù)參數(shù)標(biāo)簽和參數(shù)名稱
- 函數(shù)類型
- 嵌套函數(shù)

** 1、函數(shù)定義與調(diào)用**
當(dāng)你定義一個(gè)函數(shù)時(shí)晶通,你可以定義一個(gè)或多個(gè)有名字和類型的值璃氢,作為函數(shù)的輸入,稱為參數(shù)狮辽,也可以定義某種類型的值作為函數(shù)執(zhí)行結(jié)束時(shí)的輸出一也,稱為返回類型。每個(gè)函數(shù)有個(gè)函數(shù)名隘竭,用來描述函數(shù)執(zhí)行的任務(wù)塘秦。要使用一個(gè)函數(shù)時(shí),用函數(shù)名來“調(diào)用”這個(gè)函數(shù)动看,并傳給它匹配的輸入值(稱作實(shí)參)尊剔。函數(shù)的實(shí)參必須與函數(shù)參數(shù)表里參數(shù)的順序一致。
下面例子中的函數(shù)的名字是 greet(person:) 菱皆,之所以叫這個(gè)名字,是因?yàn)檫@個(gè)函數(shù)用一個(gè)人的名字當(dāng)做輸入须误,并返回向這個(gè)人問候的語句挨稿。為了完成這個(gè)任務(wù),你需要定義一個(gè)輸入?yún)?shù)——一個(gè)叫做 person 的 String 值京痢,和一個(gè)包含給這個(gè)人問候語的 String 類型的返回值:

<pre>func greet(person:String) -> String {
let greating = "Hello," + person + "!"
return greating;
}</pre>
函數(shù)調(diào)用:
<pre>let msg = greet(person: "Anna")
print(msg)
func greetAgain(person: String) -> String {
return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))
// 打印 "Hello again, Anna!"</pre>

2奶甘、 函數(shù)參數(shù)與返回值

  • 無參數(shù)函數(shù)
    <pre> func sayHelloWorld() -> String {
    return "hello, world"
    }
    let say = sayHelloWorld()
    print(say)
    // 打印 "hello, world"</pre>
  • 多參數(shù)函數(shù)(嵌套)
    <pre> func greetting(person:String, alreadyGreated: Bool) -> String {
    if alreadyGreated {
    return greetAgain(person: person)
    }else {
    return greet(person: person)
    }
    }
    let hello = greetting(person: "Tim", alreadyGreated: true)
    print(hello)
    // 打印 " Hello again, Tim! "</pre>
  • 無返回值函數(shù)
    func greet1(person: String) {
    print("Hello, (person)!")
    }
    greet1(person: "Dave")
    // 打印 "Hello, Dave!"

    注:因?yàn)檫@個(gè)函數(shù)不需要返回值,所以這個(gè)函數(shù)的定義中沒有返回箭頭"->"和返回類型祭椰。

    被調(diào)用時(shí)臭家,一個(gè)函數(shù)的返回值可以被忽略:
    func printAndCount(string: String) -> Int {
    print(string)
    return string.characters.count
    }
    func printWithoutCounting(string: String) {
    let _ = printAndCount(string: string)
    }
    let count = printAndCount(string: "hello, world")
    print(count)
    // 打印 "hello, world" 并且返回值 12
    printWithoutCounting(string: "hello, world")
    // 打印 "hello, world" 但是沒有返回任何值

  • 多重返回值函數(shù)
    你可以用元組(tuple)類型讓多個(gè)值作為一個(gè)復(fù)合值從函數(shù)中返回。
    下例中定義了一個(gè)名為 minMax(array:) 的函數(shù)方淤,作用是在一個(gè) Int 類型的數(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)
    }

    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"
    
  • 可選元組返回類型
    // 如果函數(shù)返回的元組類型有可能整個(gè)元組都“沒有值”,你可以使用可選的( optional ) 元組返回類型反映整個(gè)元組可以是nil的事實(shí)携茂。你可以通過在元組類型的右括號(hào)后放置一個(gè)問號(hào)來定義一個(gè)可選元組你踩,例如 (Int, Int)? 或 (String, Int, Bool)?
    為了安全地處理這個(gè)“空數(shù)組”問題,將 minMax(array:) 函數(shù)改寫為使用可選元組返回類型讳苦,并且當(dāng)數(shù)組為空時(shí)返回 nil :
    <pre>func minAndMax(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)
    }

    if let bounds1 = minAndMax(array: [8, -6, 2, 109, 3, 71]) {
    print("min is (bounds1.min) and max is (bounds1.max)")
    }
    // 打印 "min is -6 and max is 109" </pre>

3带膜、函數(shù)參數(shù)標(biāo)簽和參數(shù)名稱

每個(gè)函數(shù)參數(shù)都有一個(gè)參數(shù)標(biāo)簽( argument label )以及一個(gè)參數(shù)名稱( parameter name )。
參數(shù)標(biāo)簽在調(diào)用函數(shù)的時(shí)候使用,調(diào)用的時(shí)候需要將函數(shù)的參數(shù)標(biāo)簽寫在對應(yīng)的參數(shù)前面鸳谜。
參數(shù)名稱在函數(shù)的實(shí)現(xiàn)中使用膝藕。默認(rèn)情況下,函數(shù)參數(shù)使用參數(shù)名稱來作為它們的參數(shù)標(biāo)簽卿堂。

    func someFunction(firstParameterName: Int, secondParameterName: Int) {
        // 在函數(shù)體內(nèi)束莫,firstParameterName 和 secondParameterName 代表參數(shù)中的第一個(gè)和第二個(gè)參數(shù)值
    }
    someFunction(firstParameterName: 1, secondParameterName: 2)

所有的參數(shù)都必須有一個(gè)獨(dú)一無二的名字懒棉。雖然多個(gè)參數(shù)擁有同樣的參數(shù)標(biāo)簽是可能的草描,但是一個(gè)唯一的函數(shù)標(biāo)簽?zāi)軌蚴鼓愕拇a更具可讀性。

  • 指定參數(shù)標(biāo)簽
    你可以在函數(shù)名稱前指定它的參數(shù)標(biāo)簽策严,中間以空格分隔:

    func someFunction1(argumentLabel parameterName: Int) {
        // 在函數(shù)體內(nèi)穗慕,parameterName 代表參數(shù)值
    }
    

這個(gè)版本的 greet(person:) 函數(shù),接收一個(gè)人的名字和他的家鄉(xiāng)妻导,并且返回一句問候:

    func greetA(person name: String, from hometown: String) -> String {
        return "Hello \(name)!  Glad you could visit from \(hometown)."
    }
    print(greetA(person: "Bill", from: "Cupertino"))
    // 打印 "Hello Bill! Glad you could visit from Cupertino."

參數(shù)標(biāo)簽的使用能夠讓一個(gè)函數(shù)在調(diào)用時(shí)更有表達(dá)力逛绵,更類似自然語言,并且仍保持了函數(shù)內(nèi)部的可讀性以及清 晰的意圖倔韭。

  • 忽略參數(shù)標(biāo)簽

如果你不希望為某個(gè)參數(shù)添加一個(gè)標(biāo)簽术浪,可以使用一個(gè)下劃線( _ )來代替一個(gè)明確的參數(shù)標(biāo)簽。
<pre>func someFunction2(_ firstParameterName: Int, secondParameterName: Int) {
// 在函數(shù)體內(nèi)寿酌,firstParameterName 和 secondParameterName 代表參數(shù)中的第一個(gè)和第二個(gè)參數(shù)值
}
someFunction2(1, secondParameterName: 2)</pre>

注: 如果一個(gè)參數(shù)有一個(gè)標(biāo)簽胰苏,那么在調(diào)用的時(shí)候必須使用標(biāo)簽來標(biāo)記這個(gè)參數(shù)。

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

你可以在函數(shù)體中通過給參數(shù)賦值來為任意一個(gè)參數(shù)定義默認(rèn)值(Deafult Value)醇疼。當(dāng)默認(rèn)值被定義后硕并,調(diào)用這 個(gè)函數(shù)時(shí)可以忽略這個(gè)參數(shù)法焰。

    func someFunction3(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
        // 如果你在調(diào)用時(shí)候不傳第二個(gè)參數(shù),parameterWithDefault 會(huì)值為 12 傳入到函數(shù)體中倔毙。
    }
    someFunction3(parameterWithoutDefault: 3, parameterWithDefault: 6)
    // parameterWithDefault = 6
    someFunction3(parameterWithoutDefault: 4)
    // parameterWithDefault = 12
  • 可變參數(shù)
    一個(gè)可變參數(shù)(variadic parameter)可以接受零個(gè)或多個(gè)值埃仪。
    函數(shù)調(diào)用時(shí),你可以用可變參數(shù)來指定函數(shù)參數(shù)可以被傳入不確定數(shù)量的輸入值陕赃。
    通過在變量類型名后面加入( ... )的方式來定義可變參數(shù)卵蛉。

可變參數(shù)的傳入值在函數(shù)體中變?yōu)榇祟愋偷囊粋€(gè)數(shù)組。例如么库,一個(gè)叫做 numbers 的 Double... 型可變參數(shù)毙玻,在函數(shù)體內(nèi)可以當(dāng)做一個(gè)叫 numbers 的 [Double] 型的數(shù)組常量。
下面的這個(gè)函數(shù)用來計(jì)算一組任意長度數(shù)字的算術(shù)平均數(shù)(arithmetic mean):

    func arithmeticMean(_ numbers: Double...) -> Double {
        var total: Double = 0
        for number in numbers {
            total += number
        }
        return total / Double(numbers.count)
    }
    let res1 =  arithmeticMean(1, 2, 3, 4, 5)
    print(res1)
    // 返回 3.0, 是這 5 個(gè)數(shù)的平均數(shù)廊散。
   let res2 = arithmeticMean(3, 8.25, 18.75)
    print(res2)
    // 返回 10.0, 是這 3 個(gè)數(shù)的平均數(shù)桑滩。

注意:一個(gè)函數(shù)最多只能擁有一個(gè)可變參數(shù)。

  • 輸入輸出參數(shù)

** 4允睹、 函數(shù)類型**

每個(gè)函數(shù)都有種特定的函數(shù)類型运准,函數(shù)的類型由函數(shù)的參數(shù)類型和返回類型組成。
<pre> func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}</pre>
這個(gè)例子中定義了兩個(gè)簡單的數(shù)學(xué)函數(shù):addTwoInts 和 multiplyTwoInts缭受。這兩個(gè)函數(shù)都接受兩個(gè) Int 值胁澳, 返回一個(gè) Int 值
這兩個(gè)函數(shù)的類型是 (Int, Int) -> Int ,可以解讀為“這個(gè)函數(shù)類型有兩個(gè) Int 型的參數(shù)并返回一個(gè) Int 型的值米者。
下面是另一個(gè)例子韭畸,一個(gè)沒有參數(shù),也沒有返回值的函數(shù):

<pre>func printHelloWorld() {
print("hello, world")
}</pre>
這個(gè)函數(shù)的類型是: () -> Void 蔓搞,或者叫“沒有參數(shù)胰丁,并返回 Void 類型的函數(shù)

  • 使用函數(shù)類型
    在 Swift 中,使用函數(shù)類型就像使用其他類型一樣喂分。例如锦庸,你可以定義一個(gè)類型為函數(shù)的常量或變量,并將適當(dāng)?shù)暮瘮?shù)賦值給它:
    var mathFunction: (Int, Int) -> Int = addTwoInts
    print("Result: (mathFunction(2, 3))")
    // Prints "Result: 5"

有相同匹配類型的不同函數(shù)可以被賦值給同一個(gè)變量蒲祈,就像非函數(shù)類型的變量一樣:
mathFunction = multiplyTwoInts
print("Result: (mathFunction(2, 3))")
// Prints "Result: 6"

  • 函數(shù)類型作為參數(shù)類型

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

這個(gè)例子定義了 printMathResult(::_:) 函數(shù)甘萧,
它有三個(gè)參數(shù):第一個(gè)參數(shù)叫 mathFunction ,類型是 (Int, Int) -> Int 梆掸,你可以傳入任何這種類型的函數(shù);
第二個(gè)和第三個(gè)參數(shù)叫 a 和 b 扬卷,它們的類型都是 Int ,這兩個(gè)值作為已給出的函數(shù)的輸入值酸钦。

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

你可以用函數(shù)類型作為另一個(gè)函數(shù)的返回類型怪得。你需要做的是在返回箭頭(->)后寫一個(gè)完整的函數(shù)類型。

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

如下名為 chooseStepFunction(backward:) 的函數(shù),它的返回類型是 (Int) -> Int 類型的函數(shù)汇恤。
chooseStepF unction(backward:) 根據(jù)布爾值 backwards 來返回 stepForward(:) 函數(shù)或 stepBackward(:) 函數(shù):

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

你現(xiàn)在可以用 chooseStepFunction(backward:) 來獲得兩個(gè)函數(shù)其中的一個(gè):
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 現(xiàn)在指向 stepBackward() 函數(shù)庞钢。

上面這個(gè)例子中計(jì)算出從 currentValue 逐漸接近到0是需要向正數(shù)走還是向負(fù)數(shù)走。currentValue 的初始值 是 3 因谎,這意味著 currentValue > 0 為真(true)基括,這將使得 chooseStepFunction(:) 返回 stepBackwar d(:) 函數(shù)。一個(gè)指向返回的函數(shù)的引用保存在了 moveNearerToZero 常量中财岔。

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

** 5风皿、嵌套函數(shù)**
到目前為止本章中你所見到的所有函數(shù)都叫全局函數(shù)(global functions),它們定義在全局域中匠璧。你也可以把函數(shù)定義在別的函數(shù)體中桐款,稱作嵌套函數(shù)(nested functions)。
默認(rèn)情況下夷恍,嵌套函數(shù)是對外界不可見的魔眨,但是可以被它們的外圍函數(shù)(enclosing function)調(diào)用。一個(gè)外圍函數(shù)也可以返回它的某一個(gè)嵌套函數(shù)酿雪,使得這個(gè)函數(shù)可以在其他域中被使用遏暴。

你可以用返回嵌套函數(shù)的方式重寫 chooseStepFunction(backward:) 函數(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!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市指黎,隨后出現(xiàn)的幾起案子朋凉,更是在濱河造成了極大的恐慌,老刑警劉巖醋安,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杂彭,死亡現(xiàn)場離奇詭異,居然都是意外死亡吓揪,警方通過查閱死者的電腦和手機(jī)亲怠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磺芭,“玉大人赁炎,你說我怎么就攤上這事〖叵伲” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵讥裤,是天一觀的道長放棒。 經(jīng)常有香客問我,道長己英,這世上最難降的妖魔是什么间螟? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上厢破,老公的妹妹穿的比我還像新娘荣瑟。我一直安慰自己,他們只是感情好摩泪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布笆焰。 她就那樣靜靜地躺著,像睡著了一般见坑。 火紅的嫁衣襯著肌膚如雪嚷掠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天荞驴,我揣著相機(jī)與錄音不皆,去河邊找鬼。 笑死熊楼,一個(gè)胖子當(dāng)著我的面吹牛霹娄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鲫骗,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼项棠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挎峦?” 一聲冷哼從身側(cè)響起香追,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坦胶,沒想到半個(gè)月后透典,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顿苇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年峭咒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纪岁。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凑队,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幔翰,到底是詐尸還是另有隱情漩氨,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布遗增,位于F島的核電站叫惊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏做修。R本人自食惡果不足惜霍狰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一抡草、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔗坯,春花似錦康震、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鼎兽,卻和暖如春答姥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谚咬。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工鹦付, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人择卦。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓敲长,卻偏偏與公主長得像,于是被迫代替她去往敵國和親秉继。 傳聞我的和親對象是個(gè)殘疾皇子祈噪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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

  • 86.復(fù)合 Cases 共享相同代碼塊的多個(gè)switch 分支 分支可以合并, 寫在分支后用逗號(hào)分開。如果任何模式...
    無灃閱讀 1,370評(píng)論 1 5
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語閱讀 3,837評(píng)論 0 6
  • 2014年的蘋果全球開發(fā)者大會(huì)(WWDC)尚辑,當(dāng)Craig Federighi向全世界宣布“We have new ...
    yeshenlong520閱讀 2,294評(píng)論 0 9
  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出辑鲤,用來撰寫 OS X 和 iOS 應(yīng)用程序 ...
    大L君閱讀 3,221評(píng)論 3 25
  • 2017年11月15日星期三晴 今天上午第四節(jié)課是微機(jī)課,我們?nèi)チ宋C(jī)教室杠茬,可老師說我們太吵就讓我們下來了月褥,...
    盧慧寧閱讀 219評(píng)論 0 1