Functions (函数)

作者: 金旭峰 | 来源:发表于2017-01-16 10:55 被阅读26次

    Functionsare self-contained chunks of code that perform a specific task. You give a function a name that identifies what it does, and this name is used to “call” the function to perform its task when needed.

    函数是一段完成特定任务的独立代码片段。你可以通过给函数命名来标识某个函数的功能,这个名字可以被用来在需要的时候"调用"这个函数来完成它的任务。

    Swift’s unified function syntax is flexible enough to express anything from a simple C-style function with no parameter names to a complex Objective-C-style method with names and argument labels for each parameter. Parameters can provide default values to simplify function calls and can be passed as in-out parameters, which modify a passed variable once the function has completed its execution.

    Swift 统一的函数语法非常的灵活,可以用来表示任何函数,包括从最简单的没有参数名字的 C 风格函数,到复杂的带局部和外部参数名的Objective-C风格函数。参数可以提供默认值,以简化函数调用。参数也可以既当做传入参数,也当做传出参数,也就是说,一旦函数执行结束,传入的参数值将被修改。

    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中,每个函数都有一个由函数的参数值类型和返回值类型组成的类型。你可以把函数类型当做任何其他普通变量类型一样处理,这样就可以更简单地把函数当做别的函数的参数,也可以从其他函数中返回函数。函数的定义可以写在其他函数定义中,这样可以在嵌套函数范围内实现功能封装。

    Defining and Calling Functions (函数的定义和调用)

    When you define a function, you can optionally define one or more named, typed values that the function takes as input, known asparameters. You can also optionally define a type of value that the function will pass back as output when it is done, known as itsreturn type.

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

    Every function has afunction name, which describes the task that the function performs. To use a function, you “call” that function with its name and pass it input values (known asarguments) that match the types of the function’s parameters. A function’s arguments must always be provided in the same order as the function’s parameter list.

    每个函数有个函数名,用来描述函数执行的任务。要使用一个函数时,用函数名来“调用”这个函数,并传给它匹配的输入值(称作实参)。函数的实参必须与函数参数表里参数的顺序一致。

    The function in the example below is calledgreet(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—aStringvalue calledperson—and a return type ofString, which will contain a greeting for that person:

    下面例子中的函数的名字是greet(person:),之所以叫这个名字,是因为这个函数用一个人的名字当做输入,并返回向这个人问候的语句。为了完成这个任务,你需要定义一个输入参数——一个叫做person的String值,和一个包含给这个人问候语的String类型的返回值:

    func greet(person:String) ->String{

        let greeting="Hello, "+person+"!"

        return greeting

    }

    All of this information is rolled up into the function’sdefinition, which is prefixed with thefunckeyword. You indicate the function’s return type with thereturn arrow->(a hyphen followed by a right angle bracket), which is followed by the name of the type to return.

    所有的这些信息汇总起来成为函数的定义,并以func作为前缀。指定函数返回类型时,用返回箭头->(一个连字符后跟一个右尖括号)后跟返回类型的名称的方式来表示。

    The definition describes what the function does, what it expects to receive, and what it returns when it is done. The definition makes it easy for the function to be called unambiguously from elsewhere in your code:

    该定义描述了函数的功能,它期望接收什么作为参数和执行结束时它返回的结果是什么类型。这样的定义使得函数可以在别的地方以一种清晰的方式被调用:

    print(greet(person:"Anna"))

        // Prints "Hello, Anna!"

    print(greet(person:"Brian"))

        // Prints "Hello, Brian!"

    You call thegreet(person:)function by passing it aStringvalue after thepersonargument label, such asgreet(person: "Anna"). Because the function returns aStringvalue,greet(person:)can be wrapped in a call to theprint(_:separator:terminator:)function to print that string and see its return value, as shown above.

    调用greet(person:)函数时,在圆括号中传给它一个String类型的实参,例如greet(person: "Anna")。正如上面所示,因为这个函数返回一个String类型的值,所以greet可以被包含在print(_:separator:terminator:)的调用中,用来输出这个函数的返回值。

    Note

    The print(_:separator:terminator:)function doesn’t have a label for its first argument, and its other arguments are optional because they have a default value. These variations on function syntax are discussed below inFunction Argument Labels and Parameter NamesandDefault Parameter Values.

    print(_:separator:terminator:)函数的第一个参数并没有设置一个标签,而其他的参数因为已经有了默认值,因此是可选的。关于这些函数语法上的变化详见下方关于 函数参数标签和参数名 以及 默认参数值。

    The body of thegreet(person:)function starts by defining a newStringconstant calledgreetingand setting it to a simple greeting message. This greeting is then passed back out of the function using thereturnkeyword. In the line of code that saysreturn greeting, the function finishes its execution and returns the current value ofgreeting.

    在greet(person:)的函数体中,先定义了一个新的名为greeting的String常量,同时,把对personName的问候消息赋值给了greeting。然后用return关键字把这个问候返回出去。一旦return greeting被调用,该函数结束它的执行并返回greeting的当前值。

    You can call thegreet(person:)function multiple times with different input values. The example above shows what happens if it is called with an input value of"Anna", and an input value of"Brian". The function returns a tailored greeting in each case.

    你可以用不同的输入值多次调用greet(person:)。上面的例子展示的是用"Anna"和"Brian"调用的结果,该函数分别返回了不同的结果。

    To make the body of this function shorter, you can combine the message creation and the return statement into one line:

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

    func greetAgain(person:String) ->String{

         return"Hello again, "+person+"!"

    }

    print(greetAgain(person:"Anna"))

    // Prints "Hello again, Anna!"

    Function Parameters and Return Values (函数参数与返回值)

    Function parameters and return values are extremely flexible in Swift. You can define anything from a simple utility function with a single unnamed parameter to a complex function with expressive parameter names and different parameter options.

    函数参数与返回值在 Swift 中非常的灵活。你可以定义任何类型的函数,包括从只带一个未名参数的简单函数到复杂的带有表达性参数名和不同参数选项的复杂函数。

    Functions Without Parameters (无参数函数)

    Functions are not required to define input parameters. Here’s a function with no input parameters, which always returns the sameStringmessage whenever it is called:

    函数可以没有参数。下面这个函数就是一个无参数函数,当被调用时,它返回固定的String消息:

    func sayHelloWorld() ->String{

         return"hello, world"

    }

    print(sayHelloWorld())

    // Prints "hello, world"

    The function definition still needs parentheses after the function’s name, even though it does not take any parameters. The function name is also followed by an empty pair of parentheses when the function is called.

    尽管这个函数没有参数,但是定义中在函数名后还是需要一对圆括号。当被调用时,也需要在函数名后写一对圆括号。

    Functions With Multiple Parameters (多参数函数)

    Functions can have multiple input parameters, which are written within the function’s parentheses, separated by commas.

    函数可以有多种输入参数,这些参数被包含在函数的括号之中,以逗号分隔。

    This function takes a person’s name and whether they have already been greeted as input, and returns an appropriate greeting for that person:

    下面这个函数用一个人名和是否已经打过招呼作为输入,并返回对这个人的适当问候语:

    func greet(person:String,alreadyGreeted:Bool) ->String{

        if alreadyGreeted{

            returngreetAgain(person:person)

        } else {

          returngreet(person:person)

       }

    }

    print(greet(person:"Tim",alreadyGreeted:true))

    // Prints "Hello again, Tim!"

    You call thegreet(person:alreadyGreeted:)function by passing it both aStringargument value labeledpersonand aBoolargument value labeledalreadyGreetedin parentheses, separated by commas. Note that this function is distinct from thegreet(person:)function shown in an earlier section. Although both functions have names that begin withgreet, thegreet(person:alreadyGreeted:)function takes two arguments but thegreet(person:)function takes only one.

    你可以通过在括号内使用逗号分隔来传递一个String参数值和一个标识为alreadyGreeted的Bool值,来调用greet(person:alreadyGreeted:)函数。注意这个函数和上面greet(person:)是不同的。虽然它们都有着同样的名字greet,但是greet(person:alreadyGreeted:)函数需要两个参数,而greet(person:)只需要一个参数。

    Functions Without Return Values (无返回值的函数)

    Functions are not required to define a return type. Here’s a version of thegreet(person:)function, which prints its ownStringvalue rather than returning it:

    函数可以没有返回值。下面是greet(person:)函数的另一个版本,这个函数直接打印一个String值,而不是返回它:

    func greet(person:String) {

        print("Hello,\(person)!")

    }

      greet(person:"Dave")

    // Prints "Hello, Dave!"

    Because it does not need to return a value, the function’s definition does not include the return arrow (->) or a return type.

    因为这个函数不需要返回值,所以这个函数的定义中没有返回箭头(->)和返回类型。

    Note

    Strictly speaking, this version of thegreet(person:)functiondoesstill return a value, even though no return value is defined. Functions without a defined return type return a special value of typeVoid. This is simply an empty tuple, which is written as().

    严格上来说,虽然没有返回值被定义,greet(person:)函数依然返回了值。没有定义返回类型的函数会返回一个特殊的Void值。它其实是一个空的元组(tuple),没有任何元素,可以写成()。

    The return value of a function can be ignored when it is called:

    被调用时,一个函数的返回值可以被忽略:

    func printAndCount(string:String) ->Int{

            print(string)

            returnstring.characters.count

    }

    func printWithoutCounting(string:String) {

            let_=printAndCount(string:string)

    }

    printAndCount(string:"hello, world")

    // prints "hello, world" and returns a value of 12

    printWithoutCounting(string:"hello, world")

    // prints "hello, world" but does not return a value

    The first function,printAndCount(string:), prints a string, and then returns its character count as anInt. The second function,printWithoutCounting(string:), calls the first function, but ignores its return value. When the second function is called, the message is still printed by the first function, but the returned value is not used.

    第一个函数printAndCount(string:),输出一个字符串并返回Int类型的字符数。第二个函数printWithoutCounting(string:)调用了第一个函数,但是忽略了它的返回值。当第二个函数被调用时,消息依然会由第一个函数输出,但是返回值不会被用到。

    Note

    Return values can be ignored, but a function that says it will return a value must always do so. A function with a defined return type cannot allow control to fall out of the bottom of the function without returning a value, and attempting to do so will result in a compile-time error.

    返回值可以被忽略,但定义了有返回值的函数必须返回一个值,如果在函数定义底部没有返回任何值,将导致编译时错误(compile-time error)。

    Functions with Multiple Return Values (多重返回值函数)

    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)类型让多个值作为一个复合值从函数中返回。

    The example below defines a function calledminMax(array:), which finds the smallest and largest numbers in an array ofIntvalues:

    下例中定义了一个名为minMax(array:)的函数,作用是在一个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)

    }

    TheminMax(array:)function returns a tuple containing twoIntvalues. These values are labeledminandmaxso that they can be accessed by name when querying the function’s return value.

    minMax(array:)函数返回一个包含两个Int值的元组,这些值被标记为min和max,以便查询函数的返回值时可以通过名字访问它们。

    The body of theminMax(array:)function starts by setting two working variables calledcurrentMinandcurrentMaxto the value of the first integer in the array. The function then iterates over the remaining values in the array and checks each value to see if it is smaller or larger than the values ofcurrentMinandcurrentMaxrespectively. Finally, the overall minimum and maximum values are returned as a tuple of twoIntvalues.

    在minMax(array:)的函数体中,在开始的时候设置两个工作变量currentMin和currentMax的值为数组中的第一个数。然后函数会遍历数组中剩余的值并检查该值是否比currentMin和currentMax更小或更大。最后数组中的最小值与最大值作为一个包含两个Int值的元组返回。

    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"

    Note that the tuple’s members do not need to be named at the point that the tuple is returned from the function, because their names are already specified as part of the function’s return type.

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

    Optional Tuple Return Types (可选元组返回类型)

    If the tuple type to be returned from a function has the potential to have “no value” for the entire tuple, you can use anoptionaltuple return type to reflect the fact that the entire tuple can benil. 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)?.

    如果函数返回的元组类型有可能整个元组都“没有值”,你可以使用可选的(optional) 元组返回类型反映整个元组可以是nil的事实。你可以通过在元组类型的右括号后放置一个问号来定义一个可选元组,例如(Int, Int)?或(String, Int, Bool)?

    Note

    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.

    可选元组类型如(Int, Int)?与元组包含可选类型如(Int?, Int?)是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。

    TheminMax(array:)function above returns a tuple containing twoIntvalues. However, the function does not perform any safety checks on the array it is passed. If thearrayargument contains an empty array, theminMax(array:)function, as defined above, will trigger a runtime error when attempting to accessarray[0].

    前面的minMax(array:)函数返回了一个包含两个Int值的元组。但是函数不会对传入的数组执行任何安全检查,如果array参数是一个空数组,如上定义的minMax(array:)在试图访问array[0]时会触发一个运行时错误(runtime error)。

    To handle an empty array safely, write theminMax(array:)function with an optional tuple return type and return a value ofnilwhen the array is empty:

    为了安全地处理这个“空数组”问题,将minMax(array:)函数改写为使用可选元组返回类型,并且当数组为空时返回nil:

    func minMax(array: [Int]) -> (min:Int,max:Int)? {

        if array.isEmpty{returnnil}

        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)

    }

    You can use optional binding to check whether this version of theminMax(array:)function returns an actual tuple value or nil:

    你可以使用可选绑定来检查minMax(array:)函数返回的是一个存在的元组值还是nil:

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

    Function Argument Labels and Parameter Names (函数参数标签和参数名称)

    Each function parameter has both anargument labeland aparameter 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.

    每个函数参数都有一个参数标签( argument label )以及一个参数名称( parameter name )。参数标签在调用函数的时候使用;调用的时候需要将函数的参数标签写在对应的参数前面。参数名称在函数的实现中使用。默认情况下,函数参数使用参数名称来作为它们的参数标签。

    func someFunction(firstParameterName:Int,secondParameterName:Int) {

    // In the function body, firstParameterName and secondParameterName

    // refer to the argument values for the first and second parameters.

    // 在函数体内,firstParameterName 和 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.

    所有的参数都必须有一个独一无二的名字。虽然多个参数拥有同样的参数标签是可能的,但是一个唯一的函数标签能够使你的代码更具可读性。

    Specifying Argument Labels (指定参数标签)

    You write an argument label before the parameter name, separated by a space:

    你可以在函数名称前指定它的参数标签,中间以空格分隔:

    func someFunction(argumentLabelparameterName:Int) {

    // In the function body, parameterName refers to the argument value

    // for that parameter.

    }

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

    这个版本的greet(person:)函数,接收一个人的名字和他的家乡,并且返回一句问候:

    func greet(person:String,fromhometown: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.

    参数标签的使用能够让一个函数在调用时更有表达力,更类似自然语言,并且仍保持了函数内部的可读性以及清晰的意图。

    Omitting Argument Labels (忽略参数标签)

    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) {

    // In the function body, firstParameterName and secondParameterName

    // refer to the argument values for the first and second parameters.

    }

    someFunction(1,secondParameterName:2)

    If a parameter has an argument label, the argumentmustbe labeled when you call the function.

    如果一个参数有一个标签,那么在调用的时候必须使用标签来标记这个参数。

    Default Parameter Values (默认参数值)

    You can define adefault valuefor any parameter in a function by assigning a value to the parameter after that parameter’s type. If a default value is defined, you can omit that parameter when calling the function.

    你可以在函数体中通过给参数赋值来为任意一个参数定义默认值(Deafult Value)。当默认值被定义后,调用这个函数时可以忽略这个参数。

    func someFunction(parameterWithoutDefault:Int, parameterWithDefault:Int=12) {

    // If you omit the second argument when calling this function, then

    // the value of parameterWithDefault is 12 inside the function body.

    }

    someFunction(parameterWithoutDefault:3, parameterWithDefault:6)// parameterWithDefault is 6

    someFunction(parameterWithoutDefault:4)// parameterWithDefault is 12

    Place parameters that don’t have default values at the beginning of a function’s parameter list, before the parameters that have default values. Parameters that don’t have default values are usually more important to the function’s meaning—writing them first makes it easier to recognize that the same function is being called, regardless of whether any default parameters are omitted.

    将不带有默认值的参数放在函数参数列表的最前。一般来说,没有默认值的参数更加的重要,将不带默认值的参数放在最前保证在函数调用时,非默认参数的顺序是一致的,同时也使得相同的函数在不同情况下调用时显得更为清晰。

    Variadic Parameters (可变参数)

    Avariadic parameteraccepts zero or more values of a specified type. You use a variadic parameter to specify that the parameter can be passed a varying number of input values when the function is called. Write variadic parameters by inserting three period characters (...) after the parameter’s type name.

    一个可变参数(variadic parameter)可以接受零个或多个值。函数调用时,你可以用可变参数来指定函数参数可以被传入不确定数量的输入值。通过在变量类型名后面加入(...)的方式来定义可变参数。

    The values passed to a variadic parameter are made available within the function’s body as an array of the appropriate type. For example, a variadic parameter with a name ofnumbersand a type ofDouble...is made available within the function’s body as a constant array callednumbersof type[Double].

    可变参数的传入值在函数体中变为此类型的一个数组。例如,一个叫做numbers的Double...型可变参数,在函数体内可以当做一个叫numbers的[Double]型的数组常量。

    The example below calculates thearithmetic mean(also known as theaverage) for a list of numbers of any length:

    下面的这个函数用来计算一组任意长度数字的算术平均数(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

    Note

    A function may have at most one variadic parameter.

    一个函数最多只能拥有一个可变参数。

    In-Out Parameters (输入输出参数)

    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 anin-out parameterinstead.

    函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误(compile-time error)。这意味着你不能错误地更改参数值。如果你想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数(In-Out Parameters)

    You write an in-out parameter by placing theinoutkeyword right before a parameter’s type. An in-out parameter has a value that is passedinto the function, is modified by the function, and is passed backoutof the function to replace the original value. For a detailed discussion of the behavior of in-out parameters and associated compiler optimizations, seeIn-Out Parameters.

    定义一个输入输出参数时,在参数定义前加inout关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。想获取更多的关于输入输出参数的细节和相关的编译器优化,请查看输入输出参数一节。

    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.

    你只能传递变量给输入输出参数。你不能传入常量或者字面量,因为这些量是不能被修改的。当传入的参数作为输入输出参数时,需要在参数名前加&符,表示这个值可以被函数修改。

    Note

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

    输入输出参数不能有默认值,而且可变参数不能用inout标记。

    Here’s an example of a function calledswapTwoInts(_:_:), which has two in-out integer parameters calledaandb:

    下例中,swapTwoInts(_:_:)函数有两个分别叫做a和b的输入输出参数:

    func swapTwoInts(_a:inoutInt,_b:inoutInt) {

      let temporaryA=a

      a=b

      b=temporaryA

    }

    TheswapTwoInts(_:_:)function simply swaps the value ofbintoa, and the value ofaintob. The function performs this swap by storing the value ofain a temporary constant calledtemporaryA, assigning the value ofbtoa, and then assigningtemporaryAtob.

    swapTwoInts(_:_:)函数简单地交换a与b的值。该函数先将a的值存到一个临时常量temporaryA中,然后将b的值赋给a,最后将temporaryA赋值给b。

    You can call theswapTwoInts(_:_:)function with two variables of typeIntto swap their values. Note that the names ofsomeIntandanotherIntare prefixed with an ampersand when they are passed to theswapTwoInts(_:_:)function:

    你可以用两个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"

    The example above shows that the original values ofsomeIntandanotherIntare modified by theswapTwoInts(_:_:)function, even though they were originally defined outside of the function.

    从上面这个例子中,我们可以看到someInt和anotherInt的原始值在swapTwoInts(_:_:)函数中被修改,尽管它们的定义在函数体外。

    Note

    In-out parameters are not the same as returning a value from a function. TheswapTwoIntsexample above does not define a return type or return a value, but it still modifies the values ofsomeIntandanotherInt. In-out parameters are an alternative way for a function to have an effect outside of the scope of its function body.

    输入输出参数和返回值是不一样的。上面的swapTwoInts函数并没有定义任何返回值,但仍然修改了someInt和anotherInt的值。输入输出参数是函数对函数体外产生影响的另一种方式。

    Function Types (函数类型)

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

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

    For example

    例如

    func addTwoInts(_a:Int,_b:Int) ->Int{

        returna+b

    }

    func multiplyTwoInts(_a:Int,_b:Int) ->Int{

        returna*b

    }

    This example defines two simple mathematical functions calledaddTwoIntsandmultiplyTwoInts. These functions each take twoIntvalues, and return anIntvalue, which is the result of performing an appropriate mathematical operation.

    这个例子中定义了两个简单的数学函数:addTwoInts和multiplyTwoInts。这两个函数都接受两个Int值, 返回一个Int值。

    The type of both of these functions is(Int, Int) -> Int. This can be read as:“A function type that has two parameters, both of typeInt, and that returns a value of typeInt.”

    这两个函数的类型是(Int, Int) -> Int,可以解读为“这个函数类型有两个Int型的参数并返回一个Int型的值。”。

    Here’s another example, for a function with no parameters or return value:

    下面是另一个例子,一个没有参数,也没有返回值的函数:

    func printHelloWorld() {

        print("hello, world")

    }

    The type of this function is() -> Void, or “a function that has no parameters, and returnsVoid.”

    这个函数的类型是:() -> Void,或者叫“没有参数,并返回Void类型的函数”。

    Using Function Types (使用函数类型)

    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

    This can be read as:

    这段代码可以被解读为:

    “Define a variable calledmathFunction, which has a type of ‘a function that takes twoIntvalues, and returns anIntvalue.’ Set this new variable to refer to the function calledaddTwoInts.”

    ”定义一个叫做mathFunction的变量,类型是‘一个有两个Int型的参数并返回一个Int型的值的函数’,并让这个新变量指向addTwoInts函数”。

    TheaddTwoInts(_:_:)function has the same type as themathFunctionvariable, and so this assignment is allowed by Swift’s type-checker.

    addTwoInts和mathFunction有同样的类型,所以这个赋值过程在 Swift 类型检查(type-check)中是允许的。

    You can now call the assigned function with the namemathFunction:

    现在,你可以用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"

    As with any other type, you can leave it to Swift to infer the function type when you assign a function to a constant or variable:

    就像其他类型一样,当赋值一个函数给常量或变量时,你可以让 Swift 来推断其函数类型:

    let anotherMathFunction = addTwoInts

    // anotherMathFunction is inferred to be of type (Int, Int) -> Int

    Function Types as Parameter Types (函数类型作为参数类型)

    You can use a function type such as(Int, Int) -> Intas 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这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现留给函数的调用者来提供。

    Here’s an example to print the results of the math functions from above:

    下面是另一个例子,正如上面的函数一样,同样是输出某种数学运算结果:

    func printMathResult(_mathFunction: (Int,Int) ->Int,_a:Int,_b:Int) {

        print("Result:\(mathFunction(a,b))")

    }

    printMathResult(addTwoInts,3,5)

    // Prints "Result: 8"

    This example defines a function calledprintMathResult(_:_:_:), which has three parameters. The first parameter is calledmathFunction, 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 calledaandb, and are both of typeInt. These are used as the two input values for the provided math function.

    这个例子定义了printMathResult(_:_:_:)函数,它有三个参数:第一个参数叫mathFunction,类型是(Int, Int) -> Int,你可以传入任何这种类型的函数;第二个和第三个参数叫a和b,它们的类型都是Int,这两个值作为已给出的函数的输入值。

    When printMathResult(_:_:_:)is called, it is passed theaddTwoInts(_:_:)function, and the integer values3and5. It calls the provided function with the values3and5, and prints the result of8.

    当printMathResult(_:_:_:)被调用时,它被传入addTwoInts函数和整数3和5。它用传入3和5调用addTwoInts,并输出结果:8。

    The role ofprintMathResult(_:_:_:)is to print the result of a call to a math function of an appropriate type. It doesn’t matter what that function’s implementation actually does—it matters only that the function is of the correct type. This enablesprintMathResult(_:_:_:)to hand off some of its functionality to the caller of the function in a type-safe way.

    printMathResult(_:_:_:)函数的作用就是输出另一个适当类型的数学函数的调用结果。它不关心传入函数是如何实现的,只关心传入的函数是不是一个正确的类型。这使得printMathResult(_:_:_:)能以一种类型安全(type-safe)的方式将一部分功能转给调用者实现。

    Function Types as Return Types (函数类型作为返回类型)

    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 calledstepForward(_:)andstepBackward(_:). ThestepForward(_:)function returns a value one more than its input value, and thestepBackward(_:)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:Int) ->Int{

        return input+1

    }

    func stepBackward(_input:Int) ->Int{

    return input-1

    }

    Here’s a function calledchooseStepFunction(backward:), whose return type is(Int) -> Int. ThechooseStepFunction(backward:)function returns thestepForward(_:)function or thestepBackward(_:)function based on a Boolean parameter calledbackward:

    如下名为chooseStepFunction(backward:)的函数,它的返回类型是(Int) -> Int类型的函数。chooseStepFunction(backward:)根据布尔值backwards来返回stepForward(_:)函数或stepBackward(_:)函数:

    func chooseStepFunction(backward:Bool) -> (Int) ->Int{

        return backward?stepBackward:stepForward

    }

    You can now usechooseStepFunction(backward:)to obtain a function that will step in one direction or the other:

    你现在可以用chooseStepFunction(backward:)来获得两个函数其中的一个:

    var currentValue=3

    let moveNearerToZero=chooseStepFunction(backward:currentValue>0)

    // moveNearerToZero now refers to the stepBackward() function

    The preceding example determines whether a positive or negative step is needed to move a variable calledcurrentValueprogressively closer to zero.currentValuehas an initial value of3, which means thatcurrentValue > 0returnstrue, causingchooseStepFunction(backward:)to return thestepBackward(_:)function. A reference to the returned function is stored in a constant calledmoveNearerToZero.

    上面这个例子中计算出从currentValue逐渐接近到0是需要向正数走还是向负数走。currentValue的初始值是3,这意味着currentValue > 0为真(true),这将使得chooseStepFunction(_:)返回stepBackward(_:)函数。一个指向返回的函数的引用保存在了moveNearerToZero常量中。

    Now thatmoveNearerToZerorefers to the correct function, it can be used to count to zero:

    现在,moveNearerToZero指向了正确的函数,它可以被用来数到零:

    print("Counting to zero:")

    // Counting to zero:

    while currentValue!=0{

    print("\(currentValue)... ")

    currentValue=moveNearerToZero(currentValue)

    }

    print("zero!")

    // 3...

    // 2...

    // 1...

    // zero!

    Nested Functions (嵌套函数)

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

    到目前为止本章中你所见到的所有函数都叫全局函数(global functions),它们定义在全局域中。你也可以把函数定义在别的函数体中,称作嵌套函数(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 function)调用。一个外围函数也可以返回它的某一个嵌套函数,使得这个函数可以在其他域中被使用。

    You can rewrite thechooseStepFunction(backward:)example above to use and return nested functions:

    你可以用返回嵌套函数的方式重写chooseStepFunction(backward:)函数:

    func chooseStepFunction(backward:Bool) -> (Int) ->Int{

      func stepForward(input:Int) ->Int {returninput+1}

        func stepBackward(input:Int) ->Int {returninput-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!

    相关文章

      网友评论

        本文标题:Functions (函数)

        本文链接:https://www.haomeiwen.com/subject/ccgubttx.html