iOS development language Swift entry---closures

Source: Internet
Author: User
Tags first string sorts

iOS development language Swift Getting started serial-closures

Closures are self-contained function code blocks that can be passed and used in code. Closures in Swift are similar to the Lambdas functions in the code blocks (blocks) in C and Objective-c, and in some other programming languages.
Closures can capture and store references to any constants and variables in the context in which they are located. This is called closed merge wrapped with these constants and variables, commonly known as closures. Swift manages all of the memory operations involved in the capture process for you.
Attention:
If you are unfamiliar with the concept of capture (capturing), don't worry, you can learn more about it in the Value capture section.
The global and nested functions described in the Functions section are actually special closures, and closures take one of the following three forms:
A global function is a closed packet that has a name but does not capture any value
A nested function is a closure that has a name and can capture values within its enclosing function domain
A closure expression is an anonymous closure that uses lightweight syntax to capture variables or constant values in its context.
Swift's closure expressions have a concise style and encourage syntax optimization in common scenarios, mainly optimized as follows:
Infer parameters and return value types with context
Implicitly returns a single-expression closure, where a single-expression closure can omit the return keyword
Parameter name abbreviation
Trailing (Trailing) closure syntax
  

Closure expressions (Closure Expressions)

Nested functions are a convenient way to name and define self-contained code modules in more complex functions. Of course, it is sometimes useful to write small, non-fully defined and named class function structures, especially if you are working with some functions and need to use other functions as arguments to the function.
A closure expression is a way to construct an inline closure using concise syntax. The closure expression provides some syntax optimizations that make writing closures straightforward. The following example of a closure expression shows how the sort function is defined and how the syntax is optimized by using several iterations. Each iteration describes the same functionality in a more concise manner.
  

Sort functions (the sort function)

The SWIFT Standard library provides a sort function that sorts the values in the known type array based on the closure function you provide for sorting based on the output type.  Once the sort is complete, the function returns a new array with the same size as the original array, which contains the same type elements that have been sorted correctly. The following closure expression example uses the Sort function to sort an array of type string alphabetically, and the following is the initial array value

let names = ["Chris""Alex""Ewa""Barry""Daniella"]

The sort function needs to pass in two parameters: an array of known types
The closure function, which needs to pass in two values that are the same as the array type, and returns a Boolean value to tell the sort function whether the first parameter passed in after the sort end is preceded or followed by the second argument. If the first parameter value appears before the second parameter value, the sort closure function needs to return true and vice versa to return false.
This example sorts an array of type string, so the sort closure function type must be (string, string)-Bool.
One way to provide a sort closure function is to compose a normal function that conforms to its type requirements and pass it in as the second parameter of the sort function:

func backwards(s1: String, s2: String) -> Bool {    return s1 > s2}var reversed = sort(names, backwards)// reversed 为 ["Ewa""Daniella""Chris""Barry""Alex"]

If the first string (S1) is greater than the second string (S2), the Backwards function returns True, indicating that S1 should appear before S2 in the new array. For characters in a string, "greater than" means "appear later in alphabetical order." This means that the letter "B" is greater than the letter "A" and the string "Tom" is greater than the string "Tim". It will be sorted alphabetically, "Barry" will be ranked after "Alex".
However, this is a rather lengthy way of essentially simply writing a single-expression function (a > B). In the following example, a closed-expression syntax can be used to better construct an inline sort closure.

Closure expressions Syntax (Closure expression Syntax)

  
The closure expression syntax has the following general form:

(parameters) ->in    statements}

The closure expression syntax can use constants, variables, and inout types as parameters, and does not provide a default value. You can also use variable parameters at the end of the parameter list. Tuples can also be used as parameters and return values.
The following example shows the code for the closure expression version that corresponds to the previous backwards function:

reversed = sort(names, { (s1: String, s2: String) -> Bool in    return s1 > s2})

It is important to note that the inline closure parameter and the return value type declaration are the same as the backwards function type declaration. In both of these ways, both are written (s1:string, s2:string), Bool. In an inline closure expression, however, both the function and the return value type are written in curly braces, not outside the curly braces.
The function body part of the closure is introduced by the keyword in. The keyword indicates that the closure parameter and the return value type definition have been completed and the closure function body is about to begin.
Because the function body part of the closure is so short that it can be rewritten into one line of code:

reversed = sort(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )

This means that the overall invocation of the sort function remains unchanged, and a pair of parentheses still wraps the entire set of parameters in the function. One of the parameters now becomes an inline closure (compared to the backwards version of the code).

Inferred type based on context (inferring type from context)

  
Because the sort closure function is passed in as a parameter to the sort function, Swift can infer the type of its parameter and return value. Sort expects the second parameter to be a function of type (string, string), bool, so actually string, string, and bool types do not need to be part of the definition of a closure expression. Because all types can be inferred correctly, the return arrows (-a) and the parentheses around the parameters can also be omitted:

sortinreturn s1 > s2 } )

In fact, in any case, when a closure constructed with an inline closure expression is passed as a parameter to a function, the parameters and return value types of the closure can be inferred, which means that you hardly need to construct any inline closures with the full format.

Single-expression closed Baoyin return (implicit return from Single-expression clossures)

A single-line expression closure can implicitly return the result of a single-line expression by hiding the return keyword, as the previous version of the example can be rewritten as:

sortin s1 > s2 } )

In this example, the second argument function type of the sort function is clear that the closure must return a bool type value. Because the closure function body contains only a single expression (S1 > S2), the expression returns the bool type value, so there is no ambiguity and the return keyword can be omitted.

Parameter name abbreviation (shorthand Argument Names)

  
The parameter name abbreviation function is automatically provided for inline functions, and you can directly 0, 1. The parameters of the closed package are called in order.
If you use a parameter name abbreviation in a closure expression, you can omit the definition of it in the closure parameter list, and the type that corresponds to the abbreviation for the parameter name is inferred from the function type. The In keyword can also be omitted, because at this point the closure expression is completely composed of the closure function body:

sort$0$1 } )

In this case, 0 and 1 represents the parameters of the first and second string types in a closure.

operator functions (Operator Functions)

  
There is actually a shorter way to write the closure expression in the example above. Swift's string type defines an implementation of the strings for the greater-than sign (>), which takes two arguments of type string as a function and returns a value of type bool. This coincides with the type of function that the second parameter of the sort function requires. Therefore, you can simply pass a greater than sign, and Swift can automatically infer that you want to use a string function that is greater than the number:

reversed = sort(names, >)

For more information about operator expressions, see operator functions.

Trailing closures (Trailing Closures)

  
If you need to pass a long closure expression as the last argument to a function, you can use a trailing closure to enhance the readability of the function. A trailing closure is a closure expression that is written after the function brackets, and the function supports calling it as the last argument.

func someFunctionThatTakesAClosure(closure: () -> ()) {    // 函数体部分}// 以下是不使用尾随闭包进行函数调用someFunctionThatTakesAClosure({    // 闭包主体部分})// 以下是使用尾随闭包进行函数调用someFunctionThatTakesAClosure() {  // 闭包主体部分}

Attention:
If the function needs only one parameter of the closure expression, you can even omit () when you use a trailing closure.
In the example above, the string sorting as the sort function parameter can be rewritten as:

sort$0$1 }

Trailing closures are useful when closures are so long that they cannot be written on a single line. For example, the array type of Swift has a map method that gets a closure expression as its only parameter. Each element in the array is called once for the closure function and returns the value that the element is mapped to (or a different type of value). The specific mapping method and return value type are specified by the closure.
When supplied to the array closure function, the map method returns a new array containing the mapped values corresponding to the original array one by one.
The following example shows how to use a trailing closure in the map method to convert an array of int t type [16,58,510] to an array containing the corresponding string type ["Onesix", "Fiveeight", "Fiveonezero"]

 LetDigitnames = [0:"Zero",1:"One",2:"both",3:"three",4:"Four",5:"Five",6:"Six",7:"Seven",8:"Eight",9:"Nine"] Letnumbers = [ -, -,510]

The above code creates a digital bit and a dictionary of English versions of their name mappings. An integer array that prepares to be converted to a string is also defined.
You can now create a corresponding string version array by passing a trailing closure to the map method of numbers. Note that calling Numbers.map does not need to include any parentheses after the map because it only needs to pass the closure expression parameter, and the closure expression parameter is written in a trailing manner:

let strings = numbers.map {    (var number) ->in    var""    while0 {        10]! + output        10    }    return output}
//strings constants are inferred as array of string types,  []//its value is [ "Onesix" ,  "Fiveeight" , Span class= "hljs-string" > "Fiveonezero" ]  

Map calls a closure expression for each element in the array. You do not need to specify the type of the input parameter number for the closure, because the type of the array to be mapped can be inferred.
The closure number parameter is declared as a variable parameter (see constant and variable parameters for a specific description of the variable), so you can modify it in the closure function body. The closure expression developed a return type of string, which indicates that the new array type that stores the mapped value is string.
The closure expression creates a string and returns each time it is called.  It computes the last digit using the remainder operator (number% 10) and obtains the mapped string using the Digitnames dictionary. Attention:
The dictionary digitnames followed by an exclamation mark (! Because the dictionary subscript returns an optional value (optional value), indicating that the key does not exist and will not find a failure.
In the example above, it guarantees that number% 10 can always be a valid subscript key for a digitnames dictionary.
Therefore, the exclamation mark can be used to force parse (FORCE-UNWRAP) to store the string type value in an optional subscript.
The string obtained from the Digitnames dictionary is added to the front of the output, and a string version of the number is created in reverse order. (in the expression number% 10, if number is 16, then return 6,58 returns 8,510 returns 0).
The number variable is then divided by 10. Because it is an integer, the remainder of the calculation is ignored. So 16 became the 1,58 became the 5,510 and became the 51.
The entire process repeats until number/= 10 is 0, and the closure will output the string, and the map function will add the string to the mapped array.
The trailing closure syntax in the example above neatly encapsulates the specific closure function after the function, instead of wrapping the entire closure in the parentheses of the map function.

Capture value (capturing values)

  
Closures can capture constants or variables in the context in which they are defined. Even though the original domain that defines these constants and variables does not already exist, closures can still reference and modify these values in the closure function body.
The simplest form of closure is a nested function, which is a function defined in the function body of another function. A nested function captures all parameters of its outer function, as well as the constants and variables defined.
The following example is a function called Makeincrementor, which contains a nested function called Incrementor. The nested function Incrementor captures two values from the context, runningtotal and amount. The makeincrementor then returns the Incrementor as a closure. Each time incrementor is called, it increases the value of runningtotal in increments of amount.

func makeIncrementor(forIncrement amount: Int) ->() -> Int {    var0    func incrementor() -> Int {        runningTotal += amount        return runningTotal    }    return incrementor}

The Makeincrementor return type is (), Int. This means that it returns a function instead of a simple type value. The function does not accept arguments on each call to return only one value of type int. For functions that return the contents of other functions, see function types as return types.
The Makeincrementor function defines an integer variable runningtotal (initially 0) to store the total number of current runs. The value is returned by Incrementor.
The makeincrementor has an int type parameter whose outer name is forincrement and the internal name is amount, which indicates how much runningtotal will increment each time the incrementor is called. The Incrementor function is used to perform the actual increment operation. The function simply causes runningtotal to increase amount and return it.
If we look at this function alone, we will find that it looks unusual:

func incrementor() -> Int {    runningTotal += amount    return runningTotal}

The Incrementor function did not get any arguments, but the runningtotal and amount variables were accessed within the function body. This is because it is implemented by capturing runningtotal and amount variables that already exist in the function body that contains it.
Because the amount variable is not modified, Incrementor actually captures and stores a copy of the variable, which is stored along with the incrementor.
However, because the value of RunningTotal is modified every time the function is called, Incrementor captures the reference to the current runningtotal variable instead of just copying the initial value of the variable. Capturing a reference guarantees that the runningtotal can continue to increase when the makeincrementor R ends and does not disappear and the next time the Incrementor function is executed.
Attention:
Determines whether to capture a reference or copy a value.
You do not need to label amount or runningtotal to declare how you want to use the embedded Incrementor function.
It also handles the memory management operations of the RunningTotal variable, which is cleared if it is no longer used by the Incrementor function.
The following code is an example of using Makeincrementor:

let incrementByTen = makeIncrementor(for10)

This example defines a constant called Incrementbyten, which points to a incrementor function that adds 10 per call. Call this function multiple times to get the following results:

incrementByTen()// 返回的值为10incrementByTen()// 返回的值为20incrementByTen()// 返回的值为30

If you create another incrementor, it will have a reference to your own independent runningtotal variable. In the following example, Incrementbysevne captures a new runningtotal variable that has no relation to the variable captured in the Incrementbyten:
Let Incrementbyseven = Makeincrementor (forincrement:7) Incrementbyseven ()//Returns a value of 7incrementByTen ()//Returns a value of 40
Attention:
If you assign a closure to a property of a class instance, and the closure captures the instance by pointing to the instance or its members, you will create a strong reference ring between the closure and the instance.
Use the capture list to break this strong reference ring. For more information, refer to cyclic strong references caused by closures.

Closures are reference types (Closures is Reference Types)

  
In the above example, Incrementbyseven and Incrementbyten are constants, but the closures that these constants point to can still increase the value of the variable they capture.  This is because both the function and the closure are reference types. Whether you assign a function/closure to a constant or a variable, you are actually setting the value of the constant/variable to a reference to the corresponding function/closure. In the above example, the reference to the closure of Incrementbyten is a constant, not the closure content itself.
This also means that if you assign a closure to two different constants/variables, two values will point to the same closure:

let alsoIncrementByTen = incrementByTenalsoIncrementByTen()// 返回的值为50

iOS development language Swift entry---closures

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.