Closure Introduction
One of the major features of Swift is the use of concise first-class function/closure syntax instead of complex blocks syntax. Hopefully we no longer need the syntax described in swift, like the Fuckingblocksyntax. (Translator Note: The prime function-you can pass functions as arguments to other functions, or return values from other functions, and either set them as variables or store them in a data structure)
Closures are self-contained blocks that can be passed and used in code.
In this article we will focus on anonymous closures (such as those defined as inline and unnamed), also known as anonymous closure. We can pass it as a parameter to other functions/methods or as a return value. Closures are extremely powerful language features that enable us to write programs faster, easier, and with fewer errors.
blocks/closures (different naming of the same concept) are widely used in cocoa and cocoa touch and are at the heart of the iOS framework.
Let's look at some closure examples and why they are so useful:
Suppose we need two functions, one to calculate the mean of the square of two numbers and the other to calculate the average of the two-digit cubic, the traditional solution would be this:
Func Square (a:float), float { return A *- float { return A * A *- float { return2.0, float { return 2.0 }
We notice that the only difference between Averagesumofsquares and Averagesumofcubes is the invocation of a square or cubic function, respectively. If I could define a general function, it would be nice to calculate the average instead of repeating the call, with two numbers and a function that uses the two numbers as arguments, we can use closures as function arguments
Func averageoffunction (a:float,b:float,f: (float, float)) float { return2 }averageoffunction (34, square) averageoffunction (34, Cube)
Here we use a named closure, and we can also use a closure expression to define an inline closure without a name.
There are many ways to define closure expressions in swift, from the most verbose to the most concise:
Averageoffunction (34inreturn x * x})
(x:float), float is the type of closure (receives a float parameter, returns a float value), return x * x is the implementation, the keyword in is the terminal, implementation follows in, let's simplify.
First we ignore the type declaration, because the type can be inferred from the Averageoffunction declaration (the compiler can infer that the function that Averageoffunction expects to pass in as a parameter needs to receive a float value and then return another float value)
Averageoffunction (34inreturn x * x})
We can also ignore the return statement
Averageoffunction (34 in x * x})
Finally we can also omit the specified parameter name, using the default parameter name of $ A (if the function receives multiple arguments, use $k as the K-1 parameter, such as $0,$1,$2 ...)
Averageoffunction (34, {$0 * $0})
In the next section, we all use the last such closure expression, and if the requirements are clear in the actual code, we recommend the use of named closures.
By passing the closure as a parameter instead of repeating the code, this programming technique greatly improves the expression of the code and avoids the error caused by the code reference and copy-pasting.
Array manipulation
Swift's standard array supports three higher-order functions: Map,filter and reduce. Objective-c's Nsarray did not implement these methods, but the open source community made up the shortfall
Map
Map is used to convert each array element through a method.
[X1, x2, ..., Xn].map (f)->[f (X1), F (x2), ..., f (xn)]
We use an array of type int to store the item amount, and want to add a character "?" after each amount, and turn the array into a string array
[10,20,45,32]-> ["Ten", " a", "a", "a")
The stupidest way-Create an empty array, traverse and transform each element of the original array, and add the result of the conversion to an empty array:
var // Note that we had to specify the type of the array or else we'll get an type error for inch Moneyarray { "\ (Money) $"}
It's common to transform the original array elements and get a new array, so we can do it in one way: map.
In swift, map is declared as a naming method for the array class:
Func Map (Transform: (T)-U)-u[]
This method takes a named function transform as a parameter, transform is responsible for turning the element type T into type U and returning an array of type U.
In the above example, T is int,u to string, and as a conversion function to map is an int to string
Stringsarray = Moneyarray.map ({")? "})
{"($)?"} is a closure that turns the amount of money into characters and adds a character to the tail?
With named parameters:
inch " (money)? "})
If you don't see it, it might be that you're not familiar with string interpolation, and then you intercept a small portion of the document:
String interpolation is a method of constructing a new string that combines constants, variables, and expressions to construct a new string, and each item to be inserted into a string needs to be preceded by a backslash () and wrapped in a pair of parentheses.
Swift String Apple Reference
Filter
Filter is used to select elements in an array element that satisfy a certain condition.
Using the example of the preceding amount, filter out the amount greater than 30 elements, the result should be [45,32]
Let's look at the traditional implementation:
var filteredarray: [Int] = for in moneyarray { if30 ) { + = [money] }}
The only thing we're interested in is Money > 30, which uses filter to define the same logic.
The filter in Swift is defined in the array class as:
Filter (includeelement: (T), Bool), t[]
When Includeelement is called on the original array element with the function includeelement that returns TRUE or FALSE, only elements that return true pass the filter
Array filtering, we simply use the
Filteredarray = Moneyarray.filter ({$0})
{$ > 30} is a filter closure, we omit the parameter name and use the default argument, the return type is implicitly inferred as bool
Reduce
The reduce method computes the combination of array elements into a single value.
We use the above example to calculate the array elements and the result should be 107 (10 + 20 + 45 + 32)
Traditional implementations:
var 0 for inch Moneyarray { = sum + Money }
And look at the number multiplication.
var 1 for inch Moneyarray { = product * Money }
The only difference between the two is the initial value of the calculation (sum of 0,product is 1) and the calculation operator (sum of +,product is *)
Reduce can be used to quickly complete such operations by specifying an initial value and a method of combining elements
In Swift, reduct is defined in the array class as
Reduce (initial:u, combine: U, T)-U
Receives two parameters, one for the initial value of type U, and the other for a function that combines elements of type U and elements of type T into a value of type U. The end result is that the entire array becomes a value of type U.
In the case where U and T are int, the initial value is the 0,combine function calculates the sum of two int
and calculations are rewritten as:
sum = Moneyarray.reduce (0, {$0 + $1})
Operators in Swift can be used to simplify the following functions:
sum = Moneyarray.reduce (0, +)
Reduce can be one of the most difficult to understand in three higher-order functions. It is important to note that the two parameter types of the Combine function are different, that is, the calculation result type, which is an array element type.
Another point to note is that when the data is large, higher-order functions are faster than traditional implementations because they can be executed in parallel (as if running on multicore), and they can be used consistently for faster execution, unless you really need a higher-custom version of Map,reduce and filter.
I'm sure that when you use Map,filter,reduct, the code quality is better. But you also need to use them in the right scenarios, and don't expect to use them to solve any problems. There is no universal truth.
Here are some closure issues as an exercise
1. Write a method Applytwice (f: (float, float), x:float), float with the function f and float value x as the parameter, and then call F two times with the x parameter. such as f (f (x))
2. Write a method Applyktimes (f: (float, float), x:float), float with function f and float value x as the parameter, and then call F K with the X parameter.
3. Use Applyktimes to achieve the K-square of X
4. Given a user class array, the class contains properties name:string and Age:int, and the map function returns an array of strings consisting of the users ' name
5. Given an dictionary array, dictionary contains the key value name and key value age, and the map function returns an array of name strings
6. Given a number array, select the odd number using the filter function
7. Given a string array, use the filter function to select a string that can be converted to int
8. Given a uiview array, use the filter function to select the Uilabel subclass
9. Use the reduce function to concatenate elements of the string array into a string, separated by a newline character
10. Use the reduce function to find the largest element in a shaped array
11. Why you cannot use reduce to achieve the average function {$ + $1/float (Array.count)}
12. When implementing a reduce function, what attributes can make the operation simpler
13. Church number in Swift (final level exercise is also the hardest)
In the second part, we will create higher-order array functions in conjunction with specific usages to explore other interesting cases.
Swift High-order function: Map,filter,reduce