Why don't value types require #escaping or explicit self as opposed to escaping closures? - swift

So this code is is an escaping closure and I do understand that it's #escaping is required because the function escapes and appends or changes completion handlers.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: #escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
completionHandlers.first?()
print(instance.x)
// Prints "100”
This simple code however doesn't require the value type to be marked as escaped even though it changed the variable x.
var x: Int = 0
func x (y: Int) {
x += y
}
x (y: 7)
print (x)
This confuses me because I don't understand why in the second code self can be assessed implicitly, but with an escaping closure self is required (if it were called).

I do understand that it's #escaping is required because the function escapes and appends or changes completion handlers.
It's not entirely clear from that phrase that you understand what #escaping means. It means that this function parameter gets stored rather than executed immediately and thrown away.
That is what happens in your first example: we are handed a () -> Void and instead of merely executing it, we append it to a persistent array.
In your second example, there is no function parameter (just a lowly Int) so the matter never arises.
The reason why the question arises for a function parameter is that functions are closures, so when a function gets stored, other stuff from its environment can get stored. That can have unintended consequences, so you have to acknowledge that you're aware of this by saying #escaping.

Related

Reduce array of closures into single closure

Suppose I have an array of closures which can all be composed with one another (i.e., endomorphisms, their input and output types are the same). How can I compose these closures into a single closure?
For reference, I was trying to design something like the following.
struct MyType {
typealias MyClosure: (T) -> T
private var myClosures: [MyClosure] = [ ... ]
public var closure: MyClosure {
get {
return ? // somehow compose all of myClosures into a single closure here
}
}
}
My first thought was to use reduce, à la myClosures.reduce(STARTING) { a, b in b(a) },
but this requires a starting value to be supplied, and then successively applies the closures to it. I don't want to apply the closures to anything (yet), but just synthesize the private list of closures into a single, public closure which can be applied later. Given the way reduce is
defined, I expect this would look something like
myClosures.reduce(identity) { a, b in compose(a, b) }
func identity(_ input: T) { return input }
func compose(a: MyClosure, b: MyClosure) -> MyClosure { return b(a) }
but the type of b(a) is T, not (T) -> T. How can this be accomplished? Is this a better way of going about closure composition?
Edit: My original answer misunderstood what your problem was. But seeing as my original answer might be useful to future readers, I'll leave it at the bottom.
Your compose function is nearly there! b(a) does not compile because MyClosure does not take another MyClosure. b(a) is invoking the closure ("function application"). not composition. Since compose returns a closure, why not return a closure? A typical closure looks like this in Swift:
{ (param) in return doSomethingTo(param) }
So let's return that!
return { (x) in return b(a(x)) }
This can be simplified to:
{ b(a($0)) } // "return" can be omitted as well!
This page (among other things) tells you how and when you can simplify closure syntaxes.
Original answer:
Using reduce is the correct choice here. The reduction operation is composition, so let's write a compose function first:
func compose<T>(_ x: #escaping (T) -> T, _ y: #escaping (T) -> T) -> (T) -> T {
{ y(x($0)) } // or { x(y($0)) } if you want it the other way
}
Then, we reduce. What's the identity? The identity is something that has these properties:
compose(identity, anything) == anything
compose(anything, identity) == anything
What function does that? The identity function!
So we get:
func reduceClosures<T>(_ closures: [(T) -> T]) -> (T) -> T {
closures.reduce({ $0 }, compose)
}

Store a Swift function and its parameter values and call it later

There are multiple functions in my app, where each have a different number of parameters
func functionOne(foo: Foo, bar: Bar)
func functionTwo(foo: Foo, bar: Bar, baz: Baz, quux: Quux)
func functionThree(foo: Foo)
The parameter values can vary.
My requirement is to press a button which will run whichever function of the above was run most recently, including its parameter values.
Storing the whole thing (function and parameters) in a variable did not work.
A function and its parameters are stored in a closure. For example:
func f(_ x: Int) {}
func g(_ x: Int, _ y: Int) {}
var saved: () -> Void = { f(1) }
saved() // this executes f(1)
saved = { g(2, 3) }
saved() // now this executes g(2, 3)
You can use #escaping and #autoclosure to store a function and its parameters as a closure in a property of your class and then call it.
Add this class to your project:
// Stored Function Class
class SFC {
static var calledFunc: (() -> Void)?
static func call(_ function: #escaping #autoclosure () -> Void) {
// Store the function
calledFunc = function
// Call it
function()
}
static func reCall() {
// Called the stored function
calledFunc?()
}
// Call this when you no longer want SFC to hold onto your function.
// Your class will not deallocate if you passed in `self` to `call()`
// as long as `calledFunc` retains your function. Setting it to `nil`
// frees it.
static func forget() {
calledFunc = nil
}
}
This is how you use it:
Wrap any function call that you want to repeat with SFC.call(). Call SFC.reCall() to call that function again.
Example:
func add(_ a: Int, _ b: Int) {
print("\(a) + \(b) = \(a + b)")
}
SFC.call(print("hello", "bye"))
SFC.reCall()
SFC.reCall()
SFC.call(add(2, 3))
SFC.reCall()
Output:
hello bye
hello bye
hello bye
2 + 3 = 5
2 + 3 = 5
How does this work?
The contents of the call to call() are automatically wrapped in a closure (that is what #autoclosure does) and passed as function. The #escaping means that you'll be hanging onto that closure after call() returns.
That closure is then assigned to the calledFunc property so that it can be called again later from reCall().
Note: If the function you are passing to call() is a member function, you'll need to explicitly specify self. For example: SFC.call(self.functionThree(foo: fooVar)). Be sure to call SFC.forget() when it's time for your class to be freed so that SFC doesn't hold onto your class instance.

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

Running methods inside a block in Swift

This is probably a dumb question, but still... I'm calling a function inside a block like this:
let makeRocks = SKAction.sequence([SKAction.runBlock(self.createMyNode),<---- here should be ()
SKAction.waitForDuration(0.1, withRange: 0.15)])
func createMyNode() {
// blabla
}
I don't get it. There should be parentheses after self.createMyNode but this still compiles. How is that so?
You're not in fact calling the function, createMyNode will be called inside SKAction.runBlock, you're simply passing it as an argument.
Take a look at the type SKAction.runBlock accepts, from the SKAction documentation:
class func runBlock(_ block: dispatch_block_t) -> SKAction
And from the GCD documentation:
typealias dispatch_block_t = () -> Void
Therefore, SKAction.runBlock accepts a function (or closure, they're the same thing), which takes no arguments and returns Void; which is exactly what you're suppling with createMyNode.
With this information it's clear to see why you don't add parentheses after createMyNode - because that would call the function, thus passing Void (the return type of createMyNode) to SKAction.runBlock, which SKAction.runBlock won't accept.
To clarify, here's another example. Say you had the function:
func takesAFunc(c: (Int, Int) -> Int) -> Void {
print(c(1, 2))
}
And you wanted to pass in a function that added the two numbers. You could write:
takesAFunc { num1, num2 in
num1 + num2
}
// Prints: 3
But alternatively, you could just pass in the + operator that accepts Ints - that's a function too. Take a look at the definition:
func +(lhs: Int, rhs: Int) -> Int
That matches the type required by takesAFunc, therefore you can write:
takesAFunc(+) // Prints: 3
runBlock wants a function as parameter which you provide here (so self.createMyNode is only a reference to the function itself).
But you can also wrap the function call in a closure like so:
let makeRocks =
SKAction.sequence([SKAction.runBlock{ self.createMyNode() },
SKAction.waitForDuration(0.1, withRange: 0.15)])

Swift curried function behaves differently from expanded version

I have a curried function in Swift:
func counter(var val: Int)() -> () {
val++
println(val)
}
According to this answer it should be equivalent to this:
func counter(var val: Int) -> (() -> ()) {
func curryFunc() {
val++
println(val)
}
return curryFunc
}
However, when I run the following code:
let x = counter(3)
x()
x()
with the first one, I get 4, 4; whereas with the second one, I get 4, 5.
I am using the release Xcode 6.0.1.
The difference is that in the first version the body of the curried function is a normal function implementation, whereas in the 2nd case there's a closure. As stated in the documentation:
Closures can capture and store references to any constants and variables from the context in which they are defined.
In your case, val is captured, and retained among consecutive calls.
Addendum - if you want to have your 2nd function to behave like the curried one, you should store the parameter in a variable declared inside the function body:
func counter(val: Int) -> (() -> ()) {
func curryFunc() {
var unretainedVal = val
unretainedVal++
println(unretainedVal)
}
return curryFunc
}
The captured value val doesn't change, so the function keeps a reference to its original value.