What is trailing closure syntax in Swift? - swift

Swift's documentation on closures states:
Swift’s closure expressions have a clean, clear style, with optimizations that encourage brief, clutter-free syntax in common scenarios. These optimizations include:
Inferring parameter and return value types from context
Implicit returns from single-expression closures
Shorthand argument names
Trailing closure syntax
What exactly is "trailing closure syntax" for Swift closures?

A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.
func doSomething(number:Int, onSuccess closure:(Int)->Void) {
closure(number * number * number)
}
doSomething(number: 100) { (numberCube) in
print(numberCube) // prints 1000000
}
The argument label onSuccess is not there in the function call. Even though the closure is included in the function parameters list, swift will take it out of the parameter block to make the code more readable.

A closure expression that is written outside of (and after) the
parentheses of the function call it supports
It is just syntactic sugar to write less and is easier to read.
Giving you a use case:
You have a function that needs a another function (or closure) as a parameter like that:
func fooFunc(paramfunc: () -> Void) {
paramfunc();
}
Calling the function and giving a function as an argument is normal. Giving it a closure means the argument you give is a nameless function written between {} and with the type signature in the beginning (it is an anonymous function).
While calling a function which needs a function as argument and writing the closure after the parenthesis or omitting the parenthesis if it is the only argument (multiple trailing closures coming in Swift 5.3) makes it trailing closure syntax.
fooFunc { () -> Void in
print("Bar");
}
fooFunc() { () -> Void in
print("Bar");
}
The parenthesis after the function name can even be omitted.

If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.
func funcWithATrailingClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
funcWithATrailingClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
funcWithATrailingClosure() {
// trailing closure's body goes here
}

When the last parameter of a function is a closure like this:
class Object {
func foo(bar: String, baz: (() -> Void)) { }
}
You can call it normally like:
let obj = Object()
obj.foo(bar: "", baz: { foo() })
or trailing like this
obj.foo(bar: "") { foo() }
Also, in case of having multiple trailing closure like this:
func foo(bar: String, baz: (() -> Void), pippo: ((IndexPath) -> Void)) { }
then if you try to call it like:
obj.foo(bar: "") { _ in
} pippo: { _ in
}
following error occurs:
Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored
So prevent that error you need to call like:
obj.foo(bar: "") {
} pippo: { _ in
}
Finally, if you want to use one more closure type like Int
func foo(bar: String, baz: ((Int) -> Void), pippo: ((IndexPath) -> Void)) { }
then call like:
obj.foo(bar: "") { _ in //baz
} pippo: { _ in
}

Trailing Closures
If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.
https://docs.swift.org/swift-book/LanguageGuide/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID102
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
If a closure expression is provided as the function or method’s only argument and you provide that expression as a trailing closure, you do not need to write a pair of parentheses () after the function or method’s name when you call the function:
reversedNames = names.sorted { $0 > $1 }

Related

Converting non-escaping value to 'Any' may allow it to escape error - within not escaping function

My question is derived from the following Japanese question.
It's not my question, but I'm trying to answer the following problem but I cannot find the suitable answer.
https://teratail.com/questions/298998
The question above will be simpled like below.
func executetwice(operation:() -> Void) {
print(operation)
operation()
}
This compiler required to add #escaping keyword after operation: label, such as
func executetwice(operation: #escaping () -> Void) {
print(operation)
operation()
}
But in fact, it seems that operation block does not escape from this block.
Another way,
func executetwice(operation:() -> Void) {
let f = operation as Any
operation()
}
also compiler requires to add #escaping keyword. It is just upcasting to Any.
In other case, just casting to same type, it seems to be error.
func executetwice(operation:() -> Void) {
let f = operation as () -> Void //Converting non-escaping value to '() -> Void' may allow it to escape
operation()
}
I'm not sure why I need to add #escaping keyword with no escaping condition.
Just adding #escaping keyword will be Ok, but I would like to know why the compiler required the keyword in this case.
print accepts (a variable number of) Any as arguments, so that is why it's saying that you are converting a closure to Any when you pass it to print.
Many checks are applied on closure-typed parameters to make sure a non-escaping closure don't escape (for what it means for a closure to "escape", read this):
var c: (() -> Void)?
func f(operation:() -> Void) {
c = operation // compiler can detect that operation escapes here, and produces an error
}
However, these checks are only applied on closure types. If you cast a closure to Any, the closure loses its closure type, and the compiler can't check for whether it escapes or not. Let's suppose the compiler allowed you to cast a non-escaping closure to Any, and you passed it to g below:
var c: Any?
func g(operation: Any) {
// the compiler doesn't know that "operation" is a closure!
// You have successfully made a non-escaping closure escape!
c = operation
}
Therefore, the compiler is designed to be conservative and treats "casting to Any" as "making a closure escape".
But we are sure that print doesn't escape the closure, so we can use withoutActuallyEscaping:
func executetwice(operation:() -> Void) {
withoutActuallyEscaping(operation) {
print($0)
}
operation()
}
Casting a closure to its own type also makes the closure escape. This is because operation as () -> Void is a "rather complex" expression producing a value of type () -> Void. And by "rather complex" I mean it is complex enough that when passing that to a non-escaping parameter, the compiler doesn't bother to check whether what you are casting really is non-escaping, so it assumes that all casts are escaping.

Annotating the whole of a function declaration with a typealias

My goal is to use a typealias as a one-word reminder “attached” to a function declaration. Say,
typealias VoidToVoid = () -> ()
I can use the type alias when stating the expected type of a closure, thus
let f : VoidToVoid = { return }
assert(f is VoidToVoid)
However, this does not seem the most usual way of declaring functions. I was hoping for a way to tell the reader that a function declared like f′ below, should be of type VoidToVoid, and using that name.
(But without the reader having to infer, or to think, or to wait for the compiler to tell him or her about the type. Aggravating the situation, the compiler cannot know the type alias name I had wanted with f′ and will likely output messages stating the bare type, not the alias.)
func f′() : VoidToVoid { // tentative syntax
return
}
Can I get there at all?
Edit: There are two ends at which the type alias is to be used. At one end, this is now possible:
func giveMeAClosure(_ f: VoidToVoid) {
f()
}
At the other end, being VoidToVoid is implicit:
func canBeGivenAsClosure() {
// ...
}
That is, where canBeGivenAsClosure is declared, it is true but not obvious that there is a connection between the two ends through VoidToVoid. This is different from the let case, which can have "VoidToVoid" as its type annotation.
Closures are unnamed closure expressions, which is why we may use a function type typealias to specify the type of the closure, even for closures that have a non-empty argument list.
typealias VoidToVoid = () -> ()
typealias IntToVoid = (Int) -> ()
// unnamed closure expressions
let f: VoidToVoid = { print("foo") }
let g: IntToVoid = { print($0) }
Note here that f and g in these exaples are not functions: they are simply immutable properties that holds references to (the backing storage of) the unnamed closures specified at the time of their declaration.
A function, one the other hand, is a special case of a closure; a closure with a name. Moreover, any function with a non-empty argument list needs to supply in internal (and optionally) and external parameter names in its declaration. A function type typealias, however, may not contain argument labels for its parameter names:
typealias IntToVoid = (a: Int) -> ()
/* Error: function types cannot have argument
label 'a'; use '_' instead */
This means that a function type typealias can't possible be used a substitute for the combined parameter and return type declaration part of a function (not even in the () -> () case).
For details, see e.g.:
The Language Guide - Closures
Closures
...
Global and nested functions, as introduced in Functions, are actually
special cases of closures. Closures take one of three forms:
Global functions are closures that have a name and do not capture any values.
Nested functions are closures that have a name and can capture values from their enclosing function.
Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.
On another note, you may naturally test the type of a given function to some existing function type typealias.
typealias VoidToVoid = () -> ()
typealias IntToVoid = (Int) -> ()
func f() -> () {}
func g(_ a: Int) -> () { _ = a }
print(f is VoidToVoid) // true
print(g is IntToVoid) // true

Swift 3.0 closure expression: what if the variadic parameters not at the last place in the parameters list?

Update at 2016.09.19
There is a tricky, indirect way to use variadic parameters before some other parameters in closure expression parameters list, haha
let testClosure = { (scores: Int...) -> (_ name: String) -> String in
return { name in
return "Happy"
}
}
let k = testClosure(1, 2, 3)("John")
And I found some related issues in bugs.swift.org:
SR-2475
SR-494
Original Post
According to the document of Swift 3.0, for a closure expression, "variadic parameters can be used if you name the variadic parameter"(see Closure Expresssion Syntax part). But for Swift 2.x, the description is "Variadic parameters can be used if you name the variadic parameter and place it last in the parameter list", the border part has been removed in Swift 3.0 document, is it means variadic parameter can be a argument of closure expression even it is not at the last place? If so, why the codes below can't compile successfully?
let testClosure = { (scores: Int..., name: String) -> String in
return "Happy"
}
let k = testClosure(1, 2, 3, "John") // Missing argument for parameter #2 in call
If the argument label can be used in the call, I think the compiler can compile the code above successfully, but in Swift 3.0, closure expression's argument labels are regarded as Extraneous.
Besides, Swift 3.0 document indicates that the parameters in closure expression syntax can be in-out parameters, but Swift 3.0 said that closure expression syntax can use constant parameters, variable parameters, and inout parameters. Why Apple removed descriptions like constant parameters, variable paramters, is it because in Swift 3.0, the parameters can't be var?
Thank you very much for your help!
Still in Swift3 variadic arguments have to be the last parameter in the signature, because despite the fact that in your case the last parameter typed as String can be deduced, there's some cases where not, because of the infinite expansion of variadic argument:
let foo = { (i:Int..., j: Int) -> Int in
return j
}
foo(1,2)
...in Swift 3.0, the parameters can't be var?
var params where removed in Swift3 SE-0003 to avoid confusion with inout parameters, because both var and inout params can be assigned inside function, but just inout is reflected back.
func doSomethingWithVar(var i: Int) {
i = 2 // change visible inside function.
}
func doSomethingWithInout(inout i: Int) {
i = 2 // change reflected back to caller.
}
removing var from parameter list, remove the confusion above.
Variadic parameter have to be last and according to your situation, you can type this:
let testClosure = { (_ name: String, scores: Int...) -> String in
return "Happy"
}
let k = testClosure("John", 1, 2, 3)
You are able to create a func in Swift 3.0 where the variadic parameter is NOT the last argument. For example...
func addButtons(buttons: UIButton..., completion: (() -> ())? = nil)
I believe it's because the parameter following the variadic parameter is named, and so the func does not confuse the next named argument with more variadic arguments.
addButtons(buttons: button1, button2, button3) {
//do completion stuff
}

Escaping Closures in Swift

I'm new to Swift and I was reading the manual when I came across escaping closures. I didn't get the manual's description at all. Could someone please explain to me what escaping closures are in Swift in simple terms.
Consider this class:
class A {
var closure: (() -> Void)?
func someMethod(closure: #escaping () -> Void) {
self.closure = closure
}
}
someMethod assigns the closure passed in, to a property in the class.
Now here comes another class:
class B {
var number = 0
var a: A = A()
func anotherMethod() {
a.someMethod { self.number = 10 }
}
}
If I call anotherMethod, the closure { self.number = 10 } will be stored in the instance of A. Since self is captured in the closure, the instance of A will also hold a strong reference to it.
That's basically an example of an escaped closure!
You are probably wondering, "what? So where did the closure escaped from, and to?"
The closure escapes from the scope of the method, to the scope of the class. And it can be called later, even on another thread! This could cause problems if not handled properly.
By default, Swift doesn't allow closures to escape. You have to add #escaping to the closure type to tell the compiler "Please allow this closure to escape". If we remove #escaping:
class A {
var closure: (() -> Void)?
func someMethod(closure: () -> Void) {
}
}
and try to write self.closure = closure, it doesn't compile!
I am going in a more simpler way.
Consider this example:
func testFunctionWithNonescapingClosure(closure:() -> Void) {
closure()
}
The above is a non-escaping closure because the closure is
invoked before the method returns.
Consider the same example with an asynchoronous operation:
func testFunctionWithEscapingClosure(closure:#escaping () -> Void) {
DispatchQueue.main.async {
closure()
}
}
The above example contains an escaping closure because the closure invocation may happen after the function returns due to the asynchronous operation.
var completionHandlers: [() -> Void] = []
func testFunctionWithEscapingClosure(closure: #escaping () -> Void) {
completionHandlers.append(closure)
}
In the above case you can easily realize the closure is moving outside
body of the function so it needs to be an escaping closure.
Escaping and non escaping closure were added for compiler optimization in Swift 3. You can search for the advantages of nonescaping closure.
I find this website very helpful on that matter
Simple explanation would be:
If a closure is passed as an argument to a function and it is invoked
after the function returns, the closure is escaping.
Read more at the link I passed above! :)
By default the closures are non escaping. For simple understanding you can consider non_escaping closures as local closure(just like local variables) and escaping as global closure (just like global variables). It means once we come out from the method body the scope of the non_escaping closure is lost. But in the case of escaping closure, the memory retained the closure int the memory.
***Simply we use escaping closure when we call the closure inside any async task in the method, or method returns before calling the closure.
Non_escaping closure: -
func add(num1: Int, num2: Int, completion: ((Int) -> (Void))) -> Int {
DispatchQueue.global(qos: .background).async {
print("Background")
completion(num1 + num2) // Error: Closure use of non-escaping parameter 'completion' may allow it to escape
}
return num1
}
override func viewDidLoad() {
super.viewDidLoad()
let ans = add(num1: 12, num2: 22, completion: { (number) in
print("Inside Closure")
print(number)
})
print("Ans = \(ans)")
initialSetup()
}
Since it is non_escaping closure its scope will be lost once we come out the from the 'add' method. completion(num1 + num2) will never call.
Escaping closure:-
func add(num1: Int, num2: Int, completion: #escaping((Int) -> (Void))) -> Int {
DispatchQueue.global(qos: .background).async {
print("Background")
completion(num1 + num2)
}
return num1
}
Even if the method return (i.e., we come out of the method scope) the closure will be called.enter code here
Swift 4.1
From Language Reference: Attributes of The Swift Programming Language (Swift 4.1)
Apple explains the attribute escaping clearly.
Apply this attribute to a parameter’s type in a method or function declaration to indicate that the parameter’s value can be stored for later execution. This means that the value is allowed to outlive the lifetime of the call. Function type parameters with the escaping type attribute require explicit use of self. for properties or methods. For an example of how to use the escaping attribute, see Escaping Closures
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: #escaping () -> Void) {
completionHandlers.append(completionHandler)
}
The someFunctionWithEscapingClosure(_:) function takes a closure as its argument and adds it to an array that’s declared outside the function. If you didn’t mark the parameter of this function with #escaping, you would get a compile-time error.
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write #escaping before the parameter’s type to indicate that the closure is allowed to escape.
Definition of Escape
Swift’s closures are reference types, which means if you point two variables at the same closure they share that closure – Swift just remembers that there are two things relying on it by incrementing its reference count.
When a closure gets passed into a function to be used, Swift needs to know whether that function will get used immediately or whether it will be saved for use later on. If it’s used immediately, the compiler can skip adding one to its reference count because the closure will be run straight away then forgotten about. But if it’s used later – or even might be used later – Swift needs to add one to its reference count so that it won’t accidentally be destroyed.
Quick Example
A good example of an escaping closure is a completion handler. It’s executed in the future, when a lengthy task completes, so it outlives the function it was created in. Another example is asynchronous programming: a closure that’s executed asynchronously always escapes its original context.
public func responseData(
queue: DispatchQueue? = nil,
completionHandler: #escaping (DataResponse<Data>) -> Void)
-> Self
{
...
Extra Information
For performance reasons, Swift assumes all closures are nonescaping closures, which means they will be used immediately inside the function and not stored, which in turn means Swift doesn’t touch the reference count. If this isn’t the case – if you take any measure to store the closure – then Swift will force you to mark it as #escaping so that the reference count must be changed.
non-escaping(#noescape) vs escaping(#escaping) closure
[Function and closure]
non-escaping closure
#noescape is a closure which is passed into a function and which is called before the function returns
A good example of non-escaping closure is Array sort function - sorted(by: (Element, Element) -> Bool). This closure is called during executing a sort calculations.
History: #noescape was introduced in Swift 2 -> was deprecated in Swift 3 where became a default that is why you should mark #escaping attribute explicitly.
func foo(_ nonEscapingClosure: () -> Void) {
nonEscapingClosure()
}
escaping closure
escaping closure(reference) is alive when method was finished.
//If you have next error
Escaping closure captures non-escaping parameter
//`#escaping` to the rescue
#escaping is a closure which is
passed into a function
The owner function saves this closure in a property
closure is called(using property) after the owner function returns(async)
A good example of an escaping closure is a completion handler in asynchronous operation. If you do not mark you function with #escaping in this case you get compile time error. Reference to property in an escaping closure requires you to use self explicitly
class MyClass {
var completionHandler: (() -> Void)?
func foo(_ escapingClosure: #escaping () -> Void) {
//if you don't mark as #escaping you get
//Assigning non-escaping parameter 'escapingClosure' to an #escaping closure
completionHandler = escapingClosure //<- error here
}
func onEvent() {
completionHandler?()
}
}
completion is a completionHandlerAbout, if you want to highlight that it is #escaping you can use completionHandler naming
func foo(completion: () -> Void) {
//
}
func foo(completionHandler: #escaping () -> Void) {
//
}
[Sync vs Async]
[Java functional interfaces]
Here simple example of escaping and no escaping closures.
Non-Scaping Closures
class NonEscapingClosure {
func performAddition() {
print("Process3")
addition(10, 10) { result in
print("Process4")
print(result)
}
print("Process5")
}
func addition(_ a: Int, _ b: Int, completion: (_ result: Int) -> Void) {
print("Process1")
completion(a + b)
print("Process2")
}}
Creating an instance and calling function calling
let instance = NonEscapingClosure()
instance.performAddition()
Output:
Process3
Process1
Process4
20
Process2
Process5
And Escaping Closures
class EscapingClosure {
func performAddition() {
print("Process4")
addition(10, 10) { result in
print(result)
}
print("Process5")
}
func addition(_ a: Int, _ b: Int, completion: #escaping (_ result: Int) -> Void) {
print("Process1")
let add = a + b
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("Process2")
completion(add)
}
print("Process3")
}}
Creating an instance and function calling
let instance = EscapingClosure()
instance.performAddition()
Output
Process4
Process1
Process3
Process5
Process2
20

Using String's enumerateLines function in Swift

The enumerateLines function of Swift's String type is declared like this:
enumerateLines(body: (line: String, inout stop: Bool) -> ())
As I understand it, this declaration means: "enumerateLines is a function taking a closure, body, which is handed two variables, line and stop, and returns void."
According to the Swift Programming Language book, I believe I should thus be able to call enumerateLines in a nice terse fashion with a trailing closure, like this:
var someString = "Hello"
someString.enumerateLines()
{
// Do something with the line here
}
..but that results in a compiler error:
Tuple types '(line: String, inout stop: Bool)' and '()' have a different number of elements (2 vs. 0)
So then I try explicitly putting in the arguments, and doing away with the trailing closure:
addressString.enumerateLines((line: String, stop: Bool)
{
// Do something with the line here
})
...but that results in the error:
'(() -> () -> $T2) -> $T3' is not identical to '(line: String.Type, stop: Bool.Type)'
In short, no syntax that I've tried has resulted in anything that will successfully compile.
Could anybody point out the error in my understanding and provide a syntax that will work please? I'm using Xcode 6 Beta 4.
The closure expression syntax has the general form
{ (parameters) -> return type in
statements
}
In this case:
addressString.enumerateLines ({
(line: String, inout stop: Bool) -> () in
println(line)
})
Or, using the trailing closure syntax:
addressString.enumerateLines {
(line: String, inout stop: Bool) in
println(line)
}
Due to automatic type inference, this can be shortened to
addressString.enumerateLines {
line, stop in
println(line)
}
Update for Swift 3:
addressString.enumerateLines { (line, stop) in
print(line)
// Optionally:
if someCondition { stop = true }
}
Or, if you don't need the "stop" parameter:
addressString.enumerateLines { (line, _) in
print(line)
}