In swift, closure and function are same type as they are defined with the same format as below
A function is a particular form of closure, which includes the parameter name information, similar as closure's body implementation.
Even if a function has specified argument name, when the function is assigned to a closure variable, invoking the function by the closure variable does not need to specify the argument name as the closure variable only knows the type information without the argument name information. So once a function or closure body is assigned to a closure variable, it does not know whether the body implementation is from a function or closure.
Actually, when function or signaure used as a type, it cannot include argument label information, otherwise xcode will generate a compile error of "Function types cannot have argument labels" error. For example, the below code does not compile as (sumValue : Result, item : Element) -> Result) defines a function type with argument labels in it.
func reduce<Result>(initial : Result, sum : (sumValue : Result, item : Element) -> Result) -> Result {
var total = initial
for it in self {
total = sum(total, it)
}
return total
}
To fix the compile error, the code should be changed as
func reduce<Result>(initial : Result, sum : (Result, Element) -> Result) -> Result {
var total = initial
for it in self {
total = sum(total, it)
}
return total
}
}
The below sample shows this behavior
One unique feature to Closure is it allows specifying a capture list before parameter list to change the self or other caller scope variables to weak or unowned, as shown below
var closureargu : (Int, String)->String
The above variable can be set either to a function by assigning it to a function name, or it can be set to a closure block.A function is a particular form of closure, which includes the parameter name information, similar as closure's body implementation.
Even if a function has specified argument name, when the function is assigned to a closure variable, invoking the function by the closure variable does not need to specify the argument name as the closure variable only knows the type information without the argument name information. So once a function or closure body is assigned to a closure variable, it does not know whether the body implementation is from a function or closure.
Actually, when function or signaure used as a type, it cannot include argument label information, otherwise xcode will generate a compile error of "Function types cannot have argument labels" error. For example, the below code does not compile as (sumValue : Result, item : Element) -> Result) defines a function type with argument labels in it.
func reduce<Result>(initial : Result, sum : (sumValue : Result, item : Element) -> Result) -> Result {
var total = initial
for it in self {
total = sum(total, it)
}
return total
}
To fix the compile error, the code should be changed as
func reduce<Result>(initial : Result, sum : (Result, Element) -> Result) -> Result {
var total = initial
for it in self {
total = sum(total, it)
}
return total
}
}
The below sample shows this behavior
var handlerWithParamAndValue : (Int, String) -> String = {pi, ps in
return pi.description + " " + ps
}
func functionSample(a1 a: Int, b1 b : String) -> String {
return a.description + b.description
}
(Theoretically, the below code should not need @escaping keyword, as closure cannot be called after the function returns. However, without specifying @escaping, a compile error happens in xcode)
func someFunction(_ p1: Int, _ p2: String, clo: @escaping (Int, String)->String) -> String {
//assign function to variable
var closureargu : (Int, String)->String = functionSample
var re = closureargu(2, "def")
//assign closure variable
closureargu = handlerWithParamAndValue
re = closureargu(3, "mnq")
//assign closure body
closureargu = {p1, p2 in
return p1.description + p2.description
}
re = closureargu(4, "me")
//assign input closure parameter
closureargu = clo
re = clo(p1, p2)
re = closureargu(p1, p2)
//direct invoke function
re = functioinSample(a1: 1, b1: "hihi")
print(re)
return re
}
//call the testing method
let r = someFunction( 1, "string", clo: {(a1 , a2) in
let m = a1 + a1
return a2.description + m.description
})
One unique feature to Closure is it allows specifying a capture list before parameter list to change the self or other caller scope variables to weak or unowned, as shown below
- var asHTML: () -> String = {
- [unowned self] in
- if let text = self.text {
- return "<\(self.name)>\(text)</\(self.name)>"
- } else {
- return "<\(self.name) />"
- }
- }
Closure can update the value of the captured variables in outer scope, as long as the variable is mutable (defined by var, not by let).
No comments:
Post a Comment