swift学习笔记5 函数

注:英文部分来自官方文档

Every function in Swift has a type, consisting of the function’s parameter types and return type. You can use this type like any other type in Swift, which makes it easy to pass functions as parameters to other functions, and to return functions from functions. Functions can also be written within other functions to encapsulate useful functionality within a nested function scope.

在swift中,每个函数都有一个类型,由函数的参数类型和返回类型构成。你可以像使用swift中的其他类型一样使用该函数的类型,这使得把函数当作参数传给另一个函数或从一个函数返回另一个函数变得很容易。函数也可以写在其他函数体内,用以在一个嵌套的函数范围内封装有用的功能。

The function in the example below is called greet(person:), because that’s what it does—it takes a person’s name as input and returns a greeting for that person. To accomplish this, you define one input parameter—a String value called person—and a return type of String, which will contain a greeting for that person:

下面的函数是greet(person:),它把一个人的名字作为输入并返回一个对此人的问候。为此,你需要定义一个输入参数:一个string值,称为:person,返回一个string值,包含对此人的问候:

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

用右箭头->表明返回类型,后面跟着返回类型的名称。

  • 拥有多个返回值的函数

    You can use a tuple type as the return type for a function to return multiple values as part of one compound return value.


你可以用一个tuple类型作为一个返回多个值的函数的返回类型。
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)
}

The minMax(array:) function returns a tuple containing two Int values. These values are labeled min and max so that they can be accessed by name when querying the function’s return value.

minMax(array:)函数返回了一个包含两个int值的tuple。这两个int值被标记为min 和max,当要查询函数返回值的时候可以通过名字来获取。

Because the tuple’s member values are named as part of the function’s return type, they can be accessed with dot syntax to retrieve the minimum and maximum found values:

可以使用点语法来获取最小值和最大值:
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"
  • 可选的tuple返回类型

If the tuple type to be returned from a function has the potential to have “no value” for the entire tuple, you can use an optional tuple return type to reflect the fact that the entire tuple can be nil. You write an optional tuple return type by placing a question mark after the tuple type’s closing parenthesis, such as (Int, Int)? or (String, Int, Bool)?.

如果从函数返回的tuple类型有可能是没值的,那么你可以用可选的tuple返回类型。写法是在tuple的括号后边加上问号,比如: (Int, Int)?或(String, Int, Bool)?

An optional tuple type such as (Int, Int)? is different from a tuple that contains optional types such as (Int?, Int?). With an optional tuple type, the entire tuple is optional, not just each individual value within the tuple.

一个可选的tuple类型–比如(Int, Int)?–跟一个包含可选类型的tuple–比如 (Int?, Int?)–是不一样的。可选的tuple类型指的是整个tuple是可选的(optional),而不是值它内部包含的值是可选的。

The minMax(array:) function above returns a tuple containing two Int values. However, the function does not perform any safety checks on the array it is passed. If the array argument contains an empty array, the minMax(array:) function, as defined above, will trigger a runtime error when attempting to access array[0].

上面的minMax(array:) 函数返回一个包含两个int值的tuple。但是该函数并没有对传入的数组作安全检查,如果这个数组参数是一个空数组,那么minMax(array:)函数在获取array[0]时就会报一个runtime错误。

To handle an empty array safely, write the minMax(array:) function with an optional tuple return type and return a value of nil when the array is empty:

为了安全地处理空数组,把minMax(array:)的返回类型写为可选的tuple,当数组为空时返回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)
}

函数参数标记和参数名

Each function parameter has both an argument label and a parameter name. The argument label is used when calling the function; each argument is written in the function call with its argument label before it. The parameter name is used in the implementation of the function. By default, parameters use their parameter name as their argument label.

函数的每个参数都有参数标记和参数名。 参数标记是调用函数时使用的,每个参数在函数调用时前面都有参数标记。参数名是在函数实现里使用的。参数使用它们的参数名作为默认的参数标记。

    func someFunction(firstParameterName: Int, secondParameterName:  Int) {
        // 在函数体内, firstParameterName and secondParameterName
        // 指向第一第二个参数的值
    }
    someFunction(firstParameterName: 1, secondParameterName: 2)

All parameters must have unique names. Although it’s possible for multiple parameters to have the same argument label, unique argument labels help make your code more readable.

所有的参数都应该有一个独一无二的名字。即使多个参数可以有相同的参数标记,但是独一无二的参数标记使得你的代码更易读。
指定参数标记
参数标记写在参数名之前,用空格隔开

    func someFunction(argumentLabel parameterName: Int) {
        // 函数体内, parameterName 指向该参数的值

    }

Here’s a variation of the greet(person:) function that takes a person’s name and hometown and returns a greeting:

下面是一个 greet(person:) 函数的变体(使用了参数标记):取person的名字和家乡为输入,返回一个greeting:

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."

The use of argument labels can allow a function to be called in an expressive, sentence-like manner, while still providing a function body that is readable and clear in intent.

使用参数标记可以使得一个函数被表达式调用时更像一个句子,同时在函数内部可读性更好更清晰。
省略参数标记

If you don’t want an argument label for a parameter, write an underscore (_) instead of an explicit argument label for that parameter.

如果你不想使用参数标记,用下划线_ 取代该参数的参数标记。

    func someFunction(_ firstParameterName:Int , secondParameterName:  Int ) {
        // 在函数体内, firstParameterName and secondParameterName
        // 指向第一第二个参数的值
    }
    someFunction(1, secondParameterName: 2)

in-out 参数

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake. If you want a function to modify a parameter’s value, and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.

函数参数默认都是常量。 如果在函数内部改变一个参数的值会导致编译时错误。
这意味着你不能错误地修改参数值。如果你想在函数内修改参数的值,并且在函数调用完之后保持这种修改,那么你需要把参数定义为in-out参数。

You write an in-out parameter by placing the inout keyword right before a parameter’s type. An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.

in-out参数需要在参数类型前加上inout 关键字。in-out参数是这样一种参数:被传入函数,在函数内被修改,然后再被函数返回替代掉其原始的值。

You can only pass a variable as the argument for an in-out parameter. You cannot pass a constant or a literal value as the argument, because constants and literals cannot be modified. You place an ampersand (&) directly before a variable’s name when you pass it as an argument to an in-out parameter, to indicate that it can be modified by the function.

只能把变量传作in-out参数。不能把常量字面量传作in-out参数,因为常量字面量不可修改。
当你把变量传作in-out参数时,在其变量名之前加上&符号,表明其可被函数修改。

In-out parameters cannot have default values, and variadic parameters cannot be marked as inout.

in-out参数不能有默认值,可变参数不能标记为inout

一个例子:

    func swapTwoInts(_ a: inout   Int, _ b: inout   Int) {
        let temporaryA = a
        a = b
        b = temporaryA
    }

    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修改了。

函数类型

Every function has a specific function type, made up of the parameter types and the return type of the function.

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

    func addTwoInts(_ a:  a href="" Int /a , _ b:  a href="" Int /a ) ->  a href="" Int /a  {
        return a + b
    }
    func multiplyTwoInts(_ a:  a href="" Int /a , _ b:  a href="" Int /a ) ->  a href="" Int /a  {
        return a * b
    }
    The type of both of these functions is (Int, Int) -> Int. This can be read as:
    “A function that has two parameters, both of type Int, and that returns a value of type Int.”

这两个函数的类型都是(Int, Int) -> Int。这可以这么读:
一个接收两个类型都为int读参数并返回一个int类型的值的函数。

在一个例子;

    func printHelloWorld() {
        print("hello, world")
    }
    The type of this function is () -> Void, or “a function that has no parameters, and returns Void.”

该函数的类型是() -> Void,读作:一个没有参数,返回void的函数

使用函数类型

You use function types just like any other types in Swift. For example, you can define a constant or variable to be of a function type and assign an appropriate function to that variable:

在swift中,你可以像使用其他类型一样使用函数类型。
比如,你可以定义一个变量或常量为函数类型,并把对应的函数赋给那个变量。
var mathFunction: ( Int, Int) -> Int = addTwoInts

You can now call the assigned function with the name mathFunction:

现在你可以用名字mathFunction来调用该函数:

    print("Result: \(mathFunction(2, 3))")
    // Prints "Result: 5"

A different function with the same matching type can be assigned to the same variable, in the same way as for non-function types:

一个拥有相匹配类型的不同函数可以赋给相同的变量,就像非函数类型那样:

    mathFunction = multiplyTwoInts
    print("Result: \(mathFunction(2, 3))")
    // Prints "Result: 6"

函数类型作为参数类型

You can use a function type such as (Int, Int) -> Int as a parameter type for another function. This enables you to leave some aspects of a function’s implementation for the function’s caller to provide when the function is called.

你可以把一个函数类型—比如这样的(Int, Int) -> Int— 作为另一个函数的参数类型。
这使得你可以把一个函数的部分实现放到函数的调用者里去。
一个例子:

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

This example defines a function called printMathResult(::_:), which has three parameters. The first parameter is called mathFunction, and is of type (Int, Int) -> Int. You can pass any function of that type as the argument for this first parameter. The second and third parameters are called a and b, and are both of type Int. These are used as the two input values for the provided math function.

这个例子定义了一个函数printMathResult(::_:),此函数有三个参数。第一个参数是mathFunction,类型是(Int, Int) -> Int。你可以给第一个参数传任意此类型的函数。第二第三个参数是a和b,都是int类型。他们用作mathFunction函数的输入。

When printMathResult(:::) is called, it is passed the addTwoInts(:_:) function, and the integer values 3 and 5. It calls the provided function with the values 3 and 5, and prints the result of 8.

调用printMathResult(:::)时,传入了addTwoInts(::)函数,整数3和整数5。它调用了addTwoInts(:_:)函数,并把3和5作为输入值,最后结果打印8.

函数类型作为返回类型

You can use a function type as the return type of another function. You do this by writing a complete function type immediately after the return arrow (->) of the returning function.

你可以把一个函数类型作为另一个函数的返回类型。
只需要把完整的函数类型写在返回箭头后边。

The next example defines two simple functions called stepForward(:) and stepBackward(:). The stepForward(:) function returns a value one more than its input value, and the stepBackward(:) function returns a value one less than its input value. Both functions have a type of (Int) -> Int:

下面的两个例子定义了两个简单的函数stepForward(:) 和 stepBackward(:)。
stepForward(:)函数返回一个比它的输入值大1的值,stepBackward(:)函数返回一个比它大输入值小1的值。
两个函数都有一个类型(Int) -> Int :

    func stepForward(_ input:  a href="" Int /a ) ->  a href="" Int /a  {
        return input + 1
    }
    func stepBackward(_ input:  a href="" Int /a ) ->  a href="" Int /a  {
        return input - 1
    }

    Here’s a function called chooseStepFunction(backward:), whose return type is (Int) -> Int. The chooseStepFunction(backward:) function returns the stepForward(_:) function or the stepBackward(_:) function based on a Boolean parameter called backward:

再有一个函数chooseStepFunction(backward:),它的返回类型是(Int) -> Int。 chooseStepFunction(backward:)函数基于一个布尔参数—名字叫backward—的值来决定是返回stepForward(:)函数还是返回stepBackward(:) 函数

    func chooseStepFunction(backward:  a href="" Bool /a ) -> ( a href="" Int /a ) ->  a href="" Int /a  {
        return backward ? stepBackward : stepForward
    }

嵌套函数

All of the functions you have encountered so far in this chapter have been examples of global functions, which are defined at a global scope. You can also define functions inside the bodies of other functions, known as nested functions.

目前你在例子中看到的函数都是全局函数,定义为全局范围。你可以在其他函数内部定义函数,称为嵌套函数。

Nested functions are hidden from the outside world by default, but can still be called and used by their enclosing function. An enclosing function can also return one of its nested functions to allow the nested function to be used in another scope.

嵌套函数默认对外部隐藏,但依然可以被包围(enclosing)它的函数调用和使用。包围函数同样可以把它的嵌套函数返回,使该嵌套函数在其他范围内得以使用。

改写上面的chooseStepFunction(backward:)函数,使用和返回嵌套函数

    func chooseStepFunction(backward:  a href="" Bool /a ) -> ( a href="" Int /a ) ->  a href="" Int /a  {
        func stepForward(input:  a href="" Int /a ) ->  a href="" Int /a  { return input + 1 }
        func stepBackward(input:  a href="" Int /a ) ->  a href="" Int /a  { 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!

你可能感兴趣的:(swift)