zoukankan      html  css  js  c++  java
  • Swift3.0P1 语法指南——函数

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID158

    函数是完成指定任务的独立代码块。

    Swift中的函数都有对应的类型,由参数类型和返回值类型共同组成。你可以像使用其他类型一样来使用函数类型,因此,可以将函数作为函数的参数,也可以将函数作为函数的返回值。函数中也可以嵌套函数,实现功能封装。

    1、定义和调用函数

    当你定义一个函数时,你可以定义一个或多个有名字和类型的值,作为函数的输入(参数,parameters),也可以定义某种类型的值作为函数执行结束的输出(返回类型)。

    要使用一个函数时,你用函数名“调用”,并传给它相应的输入值(称作实参,arguments)。一个函数的实参必须与函数参数表里参数的顺序一致。

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

    输入不同的参数,返回不同的结果:

    1 print(greet(person: "Anna"))
    2 // prints "Hello, Anna!"
    3 print(greet(person: "Brian"))
    4 // prints "Hello, Brian!"

    为了简化这个函数的定义,可以将问候消息的创建和返回写成一句:

    1 func greetAgain(person: String) -> String {
    2     return "Hello again, " + person + "!"
    3 }
    4 print(greetAgain("Anna"))
    5 // prints "Hello again, Anna!"

    2、函数参数和返回值

    (1)没有参数的函数

    输入参数并不是必需的:

    1 func sayHelloWorld() -> String {
    2     return "hello, world"
    3 }
    4 print(sayHelloWorld())
    5 // prints "hello, world"

    (2)有多个参数的函数

    函数可以有多个参数,都写在括号里,并用逗号分隔。每个参数都有一个label。

    1 func greet(person: String, alreadyGreeted: Bool) -> String {
    2     if alreadyGreeted {
    3         return greetAgain(person)
    4     } else {
    5         return greet(person)
    6     }
    7 }
    8 print(greet("Tim", alreadyGreeted: true))
    9 // prints "Hello again, Tim!"

    当调用含有一个或多个参数的函数时,第一个参数之后的其他参数都会用参数名作标识。(V2.1)

    (3)没有返回值的函数

    返回值并不是必需的: 

    1 func greet(person: String) {
    2     print("Goodbye, (person)!")
    3 }
    4 sayGoodbye("Dave")
    5 // prints "Goodbye, Dave!"

    没有返回值,箭头和返回类型就不用写了。

    注意:严格来说,即使没有定义返回值,函数也必须返回一个值。没有返回值的函数实际上返回了一种特殊的值Void,这是一个空的元组,实际上也就是没有元素的元组,可以写成()。

    调用函数的时候,可以忽略它的返回值:

     1 func printAndCount(stringToPrint: String) -> Int {
     2     print(stringToPrint)
     3     return stringToPrint.characters.count
     4 }
     5 func printWithoutCounting(stringToPrint: String) {
     6     printAndCount(stringToPrint)
     7 }
     8 printAndCount("hello, world")
     9 // prints "hello, world" and returns a value of 12
    10 printWithoutCounting("hello, world")
    11 // prints "hello, world" but does not return a value

    注意:函数的返回值可以不被使用,但是函数必须声明它会返回一个值。如果函数定义了返回值类型,但在函数底部没有返回一个值,将会报编译时错误。

    (4)有多个返回值的函数

    如果有多个返回值,可以用元组来作为函数的返回类型。

     1 func minMax(array: [Int]) -> (min: Int, max: Int) {
     2     var currentMin = array[0]
     3     var currentMax = array[0]
     4     for value in array[1..<array.count] {
     5         if value < currentMin {
     6             currentMin = value
     7         } else if value > currentMax {
     8             currentMax = value
     9         }
    10     }
    11     return (currentMin, currentMax)
    12 }

    由于元组的成员名已在返回类型中声明,可以用点语法来取出元组中对应的值。

    1 let bounds = minMax([8, -6, 2, 109, 3, 71])
    2 print("min is (bounds.min) and max is (bounds.max)")
    3 // prints "min is -6 and max is 109"

    注意:元组的成员不需要在函数返回时命名,因为它们的名字已经在函数返回类型中有了定义。

    (5)可选的元组返回类型

    如果元组返回时,可能整个元组都没有值,那么,可以用可选元组来作为返回值类型,暗示返回的元组可能是nil。可选元组就是在元组的括号后面添加一个问号,例如(Int, Int)?或(String, Int, Bool)?。

    注意:(Int, Int)?和(Int?, Int?)是不同的两个概念。可选元组是整个元组可能是nil,而不是各个成员的值可能是nil。

     1 func minMax(array: [Int]) -> (min: Int, max: Int)? {
     2     if array.isEmpty { return nil }
     3     var currentMin = array[0]
     4     var currentMax = array[0]
     5     for value in array[1..<array.count] {
     6         if value < currentMin {
     7             currentMin = value
     8         } else if value > currentMax {
     9             currentMax = value
    10         }
    11     }
    12     return (currentMin, currentMax)
    13 }

    可以用可选绑定来检查函数是否返回了元组:

    1 if let bounds = minMax([8, -6, 2, 109, 3, 71]) {
    2     print("min is (bounds.min) and max is (bounds.max)")
    3 }
    4 // prints "min is -6 and max is 109"

    3、函数的参数名

    函数的参数都有一个外部参数名(argument label)和局部参数名(parameter name)。

    当调用函数时,外部参数名被用来标识参数。局部参数名则被用在函数的实现主体中。

    默认情况下,局部参数名和外部参数名是相同的。

    1 func someFunction(firstParameterName: Int, secondParameterName: Int) {
    2     // function body goes here
    3     // firstParameterName and secondParameterName refer to
    4     // the argument values for the first and second parameters
    5 }
    6 someFunction(1, secondParameterName: 2)

    一般情况下,第一个参数省略其外部参数名,第二个以后的参数使用其局部参数名作为自己的外部参数名。

    所有参数必须有不同的局部参数名(parameter name),尽管外部参数名(argument label)可以是相同的,独特的外部参数名还是能让代码更具有可读性。

    (1)指定外部参数名(Label)

    可以在本地参数名前指定外部参数名,中间以空格分隔。

    1 func someFunction(argumentLabel parameterName: Int) {
    2     // function body goes here, and can use parameterName
    3     // to refer to the argument value for that parameter
    4 }

    注意:如果提供了外部参数名,那么函数在被调用时,必须使用外部参数名。

    下面的例子中有多个参数:

    1 func greet(person: String, from hometown: String) -> String {
    2     return "Hello (person)!  Glad you could visit from (hometown)."
    3 }
    4 print(greet(person: "Bill", from: "Cupertino"))
    5 // Prints "Hello Bill!  Glad you could visit from Cupertino.

    为每个参数指定外部参数名,在你调用函数greet(person:from:)函数时两个参数都必须被标记出来。

    (2)忽略外部参数名

    如果你不想为参数设置label,可以用下划线(_)代替。

    1 func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
    2     // function body goes here
    3     // firstParameterName and secondParameterName refer to
    4     // the argument values for the first and second parameters
    5 }
    6 someFunction(1, 2)

    注意:第一个参数的外部名默认是省略的,所以 不必为它添加下划线。(V2.1

    4、默认参数值

    当默认值被定义后,调用这个函数时可以忽略这个参数。

    1 func someFunction(parameterWithDefault: Int = 12) {
    2     // function body goes here
    3     // if no arguments are passed to the function call,
    4     // value of parameterWithDefault is 12
    5 }
    6 someFunction(6) // parameterWithDefault is 6
    7 someFunction() // parameterWithDefault is 12

    注意: 带有默认值的参数要放在函数参数列表的最后。这样可以保证在函数调用时,非默认参数的顺序是一致的,同时使得相同的函数在不同情况下调用时显得更为清晰。

    5、不定参数

    不定参数(variadic parameter)可以接受零个或多个值。函数调用时,你可以用不定参数来传入不确定数量的输入参数。

    通过在变量类型名后面加入(...)的方式来定义不定参数。

    不定参数的传入值在函数体内实际是同类型的一个数组。例如,一个 Double... 型可变参数numbers,在函数体内可以当做一个叫 numbers 的 [Double] 型的数组常量。

     1 func arithmeticMean(_ numbers: Double...) -> Double {
     2     var total: Double = 0
     3     for number in numbers {
     4         total += number
     5     }
     6     return total / Double(numbers.count)
     7 }
     8 arithmeticMean(1, 2, 3, 4, 5)
     9 // returns 3.0, which is the arithmetic mean of these five numbers
    10 arithmeticMean(3, 8.25, 18.75)
    11 // returns 10.0, which is the arithmetic mean of these three numbers

    注意:每个函数最多有一个不定参数。

    6、In-Out参数

    函数的参数默认看做常量,在函数体内试图改变参数的值会报编译时错误。

    如果你想在函数中改变某个参数的值,并将这种变化保留到函数外部,那么可以将参数定义为in-out参数。

    in-out参数通过在参数类型前面加上inout关键字来定义。

    只能将变量传给in-out参数,常量和字面量不能使用。

    1 func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    2    let temporaryA = a
    3    a = b
    4    b = temporaryA
    5 }

    当把变量名传给in-out参数时,要在变量名前面加上&符号,表示函数可以修改该变量。

    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”

    注意: in-out参数不能有默认值,而且不定参数不能用 inout 标记。

    7、函数类型

    每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。

    1 func addTwoInts(_ a: Int, _ b: Int) -> Int {
    2     return a + b
    3 }
    4 func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    5     return a * b
    6 }

    上面的两个函数的函数类型都是(Int, Int) -> Int。

    另一种函数:

    1 func printHelloWorld() {
    2     print("hello, world")
    3 }

    其返回类型是() -> Void。

    (1)使用函数类型

    函数类型的使用和其他类型一样,例如,可以把一个函数赋值给一个常量或变量。

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

    这样,可以用mathFunction的名字来调用addTwoInts函数:

    1 print("Result: (mathFunction(2, 3))")
    2 // prints "Result: 5"

    同一函数类型的其他函数也可以赋值给这个变量:

    1 mathFunction = multiplyTwoInts
    2 print("Result: (mathFunction(2, 3))")
    3 // prints "Result: 6"

    由于函数推断,可以不用显示声明变量的类型:

    1 let anotherMathFunction = addTwoInts
    2 // anotherMathFunction is inferred to be of type (Int, Int) -> Int

    (2)函数类型作为参数类型

    你可以用(Int, Int) -> Int这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现交由给函数的调用者。

    1 func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    2     print("Result: (mathFunction(a, b))")
    3 }
    4 printMathResult(addTwoInts, 3, 5)
    5 // prints "Result: 8"

    (3)函数类型作为返回类型

    可以用函数类型作为另一个函数的返回类型。

    例如,下面是两个简单函数。

    1 func stepForward(_ input: Int) -> Int {
    2     return input + 1
    3 }
    4 func stepBackward(_ input: Int) -> Int {
    5     return input - 1
    6 }

    下面这个叫做 chooseStepFunction(_:) 的函数,它的返回类型是 (Int) -> Int 的函数。

    chooseStepFunction(backward:) 根据布尔值 backwards 来返回 stepForward(_:) 函数或 stepBackward(_:) 函数:

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

    可以用chooseStepFunction(_:) 来获得一个函数:

    1 var currentValue = 3
    2 let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
    3 // moveNearerToZero now refers to the stepBackward() function

    moveNearerToZero已获得了正确的函数,就可以用来将数字数到0:

     1 print("Counting to zero:")
     2 // Counting to zero:
     3 while currentValue != 0 {
     4     print("(currentValue)... ")
     5     currentValue = moveNearerToZero(currentValue)
     6 }
     7 print("zero!")
     8 // 3...
     9 // 2...
    10 // 1...
    11 // zero!

    8、嵌套函数

     1 func chooseStepFunction(backward: Bool) -> (Int) -> Int {
     2     func stepForward(_ input: Int) -> Int { return input + 1 }
     3     func stepBackward(_ input: Int) -> Int { return input - 1 }
     4     return backward ? stepBackward : stepForward
     5 }
     6 var currentValue = -4
     7 let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
     8 // moveNearerToZero now refers to the nested stepForward() function
     9 while currentValue != 0 {
    10     print("(currentValue)... ")
    11     currentValue = moveNearerToZero(currentValue)
    12 }
    13 print("zero!")
    14 // -4...
    15 // -3...
    16 // -2...
    17 // -1...
    18 // zero!
  • 相关阅读:
    [C#.NET 拾遗补漏]:迭代器和列举器
    [C#.NET 拾遗补漏]:操作符的几个骚操作
    [C#.NET 拾遗补漏]:理解 volatile 关键字
    C#-表达式目录树
    数据源管理 | 关系型分库分表,列式库分布式计算
    Java中的经典算法之冒泡排序(Bubble Sort)
    MySQL数据库优化的八种方式(经典必看)
    mysql插入数据后返回自增ID的方法(AUTO_INCREMENT)
    MySQL 插入数据后返回自增id的方法
    查询数据库中的重复数据——MySQL数据库
  • 原文地址:https://www.cnblogs.com/tt2015-sz/p/4865692.html
Copyright © 2011-2022 走看看