The first closure works. However, as soon as I take out the dummy assignment, the closure stops working (addUpClosureRedFlagged). Anyone knows why?
let addUpClosureWorking: (Int ...) -> Int = {
let dummy = "Anything" // Comment out and wait for the error...
return $0.reduce(0, combine: +)
}
let addUpClosureRedFlagged: (Int ...) -> Int = {
return $0.reduce(0, combine: +) // Should work, but doesn't!
}
addUpClosureWorking(1, 2, 3, 4, 5) // 15
If we wanted to pass that closure into a function so it can be run inside that function, we would specify the parameter type as () -> Void . That means “accepts no parameters, and returns Void ” – Swift's way of saying “nothing”.
As shown in the above table, there are three types of closures in Swift, namely global functions, nested functions, and closure expressions. They differ in several aspects, including their use scopes, their names, and whether they capture values, which will be discussed more in a later section.
Difference between Function and ClosureFunction is declared using func keyword whereas Closure doesn't have func keyword. Function has always name but Closure doesn't have. Function doesn't have in keyword but closure has in the keyword.
Swift Closure Declarationparameters - any value passed to closure. returnType - specifies the type of value returned by the closure. in (optional) - used to separate parameters/returnType from closure body.
As of current Swift (2.1), the type inference of closures can behave a bit strange when containing only a single line, see e.g. this somewhat related issue; expecting explicit inclusion of the function type signature within the closure.
This (compiler) "bug"/closure limitation is present (at least) for variadiac as well as inout
arguments:
// variadiac argument example
let fooErr1: (Int ...) -> Int = {
return $0.reduce(0, combine: +)
}
// or: let fooErr1: (Int ...) -> Int = { $0.reduce(0, combine: +) }
/* error: cannot convert value of type '(_) -> Int'
to specified type '(Int...) -> Int' */
// inout argument example
let fooErr2: (inout _: Int) -> Int = {
return $0
}
// or: let fooErr2: (inout _: Int) -> Int = { $0 }
/* error: cannot convert value of type '_ -> Int'
to specified type '(inout Int) -> Int' */
This can be avoided by explicitly including the function:s type signature in the closure, or including any statement prior to the return statement (in so extending the closure to contain more than a single line).
/* Avoiding fooErr1:
- explicitly state function type signature in closure */
let foo: (Int ...) -> Int = {
(bar: Int ...) -> Int in
return bar.reduce(0, combine: +)
}
/* - include any kind of statment prior to return statement */
let foo2: (Int ...) -> Int = {
(); return $0.reduce(0, combine: +)
}
/* Avoiding fooErr2:
- explicitly state function type signature in closure */
let foo3: (inout _: Int) -> Int = {
(inout bar: Int) -> Int in
return bar
}
/* - include any kind of statment prior to return statement */
let foo4: (inout _: Int) -> Int = {
(); return $0
}
Why? I've written "bug" above, but perhaps more of a current limitation in the type inference of closures by the compiler; as Pradeep K writes in his answer, this is most likely due to some intricacies of the Swift compiler, failing type inference in these cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With