Array of functions don't keep their values from their creation - swift

I try to manage my functions with a Manger. The problem is that the function code updates and is not saved in the moment when i add the function to my manager. I try to explain my problem with this example:
class QueueManager {
typealias FunctionType = () -> ()
private var functions = [(String, FunctionType)]()
func add(funcName: String, function: FunctionType) -> QueueManager {
functions.append(funcName, function)
return self
}
func runFirst() -> Bool {
guard functions.isEmpty == false else { return false }
functions.first!.1()
functions.removeFirst()
return true
}
}
Then i do this:
let queueManager = QueueManger()
var value = 1
queueManager.add("simpleFunction"){
print(value)
}
value = 2
queueManager.add("simpleFunction"){
print(value)
}
queueManager.runFist()
queueManager.runFist()
And the result is:
2 // Because value is 2 in both functions. But i added the function while value was 1??
2
But i want the result:
1
2
What am i doing wrong? Thanks in advance!
EDIT: Very easy playground example:
import UIKit
var str = "1"
func go() {
print(str)
}
var array:[()->()] = []
array.append(go)
str = "2"
array.append(go)
array[0]()
array[1]()
// Output:
// 2
// 2
EDIT 2:
I know that 2 2 is the right output for my code. But i want to keep the function in the state of its creation. Is this somehow possible?
EDIT 3:
Thanks for all of your help. But i think i`m failing to explain my problem enough to get suiting answers. I want to call a function with its parameters at a later time. I don't want to keep the reference to the parameter values. I just need to call the function with those parameter values.

In order to understand what happens here lets take a look step-by-step :
Assign 1 to value
Add the print instruction to QueueManager
Assign 2 to value
Add the print instruction to QueueManager
Run the functions using runFirst()
When you add the print(value) instruction you pass value as reference type. This creates a strong reference between variable functions and value. Hence when you actually execute those instructions, using runFirst() it then uses the value stored in value at that point of time.
Let's explore using this example:
var value = 5
queueManager.add(funcName: "simpleFunction"){
print(value)
}
queueManager.add(funcName: "simpleFunction"){
print(value)
}
queueManager.runFirst()
queueManager.runFirst()
value = 10
// output is 5 5
In this case we perform runFirst() first and then update the value. Hence the output is 5 5.
TL;DR - Pass By Reference causes function to print the current value of variable value.
EDIT : Bind the data to the function in QueueManager, this will make sure that the current value of data (during function definition) is associated with the function.
class QueueManager {
typealias FunctionType = (Int) -> ()
private var functions = [(String, FunctionType, Int)]()
func add(funcName: String, function: #escaping FunctionType, data: Int) -> QueueManager
{
functions.append((funcName, function, data))
return self
}
func runFirst() -> Bool
{
guard functions.isEmpty == false else { return false }
functions.first!.1(functions.first!.2)
functions.removeFirst()
return true
}
}
let queueManager = QueueManager()
// define you function within this closure
let functionClosure: (Int) -> () = { (data) in
print(data)
}
var value = 1
queueManager.add(funcName: "simpleFunction", function: functionClosure, data: value)
value = 2
queueManager.add(funcName: "simpleFunction", function: functionClosure, data: value)
queueManager.runFirst()
queueManager.runFirst()
OUTPUT :
1
2

Based on your code, obviously the result should be:
2
2
because you are calling queueManager.runFirst() tow times after editing value = 2
Also, if add function should includes functions.append((funcName, function)) then I assume that its function parameter should be #escaping as follows:
class QueueManager {
typealias FunctionType = () -> ()
private var functions = [(String, FunctionType)]()
func add(funcName: String, function: #escaping FunctionType) -> QueueManager {
functions.append((funcName, function))
return self
}
func runFirst() -> Bool {
guard functions.isEmpty == false else { return false }
functions.first!.1()
functions.removeFirst()
return true
}
}
Thus the output of:
let queueManager = QueueManager()
var value = 1
queueManager.add(funcName: "simpleFunction") {
print(value)
}
queueManager.runFirst()
value = 2
queueManager.add(funcName: "simpleFunction"){
print(value)
}
queueManager.runFirst()
should be:
1
2
because -simply- I called queueManager.runFirst() before calling value = 2
The same issue is applicable to your simple example:
var str = "1"
func go() {
print(str)
}
var array:[()->()] = []
array.append(go)
array[0]()
str = "2"
array.append(go)
array[1]()
calling array.append(go) won't leads to execute go(), you should call it by array[0](); Since you are trying to print the value of the same variable (str) it will always prints the latest value for it. If you want to save each value separately for each function, you should -somehow- declare more than one variable (value or str).

import UIKit
var str = "Hello, playground"
class QueueManager {
typealias FunctionType = () -> ()
private var functions = [(String, FunctionType)]()
func add(funcName: String, function: #escaping FunctionType) -> QueueManager {
functions.append((funcName, function))
return self
}
func runFirst() -> Bool {
guard functions.isEmpty == false else { return false }
print(functions)
functions.first!.1()
functions.removeFirst()
return true
}
}
var value = 1
let queueManager = QueueManager()
func simpleFunction(_ value: AnyObject){
print(value)
}
queueManager.add(funcName: "simpleFunction"){
simpleFunction(value as AnyObject)
}
queueManager.add(funcName: "simpleFunction"){
value = 2
simpleFunction(value as AnyObject)
}
queueManager.runFirst()
queueManager.runFirst()
You have to update your value after the first simpleFunction was added.
Playground Output:
[("simpleFunction", (Function)), ("simpleFunction", (Function))]
1
[("simpleFunction", (Function))]
2

Related

How can I define insert function for Set when Set is optional in Swift?

My goal is to be able insert new item to an optional set which this set has nil value before. For that reason i created this extension, but it does not work, and still I cannot insert a new item to a nil set.
extension Optional where Wrapped == Set<String> {
func myInsert(_ value: String) -> Self {
if let unwrappedSet: Set<String> = self {
var newSet: Set<String> = unwrappedSet
newSet.insert(value)
return newSet
}
else {
let set: Set<String>? = [value]
return set
}
}
}
use case:
func myTest() -> Set<String>? {
var set: Set<String>? = nil
set.myInsert("Hello")
return set
}
if let set: Set<String> = myTest() {
print(set)
}
I refuse to believe there is issue with my extension, and i think the issue is from xcode itself, look the function below it is same function but outside of extension, it does works!
func myInsert(set: Set<String>?, value: String) -> Set<String>? {
if let unwrappedSet: Set<String> = set {
var newSet: Set<String> = unwrappedSet
newSet.insert(value)
return newSet
}
else {
let set: Set<String>? = [value]
return set
}
}
use case:
let set: Set<String>? = nil
let newSet = myInsert(set: set, value: "Hello")
let newSet2 = myInsert(set: newSet, value: "World")
print(newSet2)
result:
Optional(Set(["Hello", "World"]))
From your test case code:
var set: Set<String>? = nil
set.myInsert("Hello")
you expect the variable set to change from nil to a wrapped Set<String> containing the String "Hello". In order for the value to modify itself, the func must be mutating.
Make myInsert a mutating func and assign the new set to self. Since myInsert is mutating, it doesn't need to return a value which your test is ignoring anyway:
extension Optional where Wrapped == Set<String> {
mutating func myInsert(_ value: String) {
if self == nil {
self = [value]
} else {
self?.insert(value)
}
}
}
Test
func myTest() -> Set<String>? {
var set: Set<String>? = nil
set.myInsert("Hello")
set.myInsert("Goodbye")
return set
}
if let set = myTest() {
print(set)
}
["Hello", "Goodbye"]
Making insert more usable
(Thanks to #LeoDabus for his suggestions)
We can make this work with a Set of any type and make it more like the original insert on Set by having it return a #discardableResult containing a tuple with a Bool indicating if a the value was inserted and the memberAfterInsert:
extension Optional where Wrapped: SetAlgebra {
#discardableResult
mutating func insert(_ newMember: Wrapped.Element) -> (inserted: Bool, memberAfterInsert: Wrapped.Element) {
if self == nil {
self = .init()
}
return self!.insert(newMember)
}
}
vacawama and Leo's answer is correct but you want to understand why your code doesn't work. I'll try to explain why does not work as you expected. The function you created "myInsert" defines a Set object, inserts the parameter value and returns the newly created Set object. The problem is you are not actually assigning the created Set object to actual Set variable (which is "self") that you are working on.
if let unwrappedSet: Set<String> = self {
var newSet: Set<String> = unwrappedSet // assigning nil valued "self" to a variable doesn't assign the original variable. Assigning nil to another variable makes that variable again nil. Both are equal (they are nil) but not same variables.
newSet.insert(value) // inserts value to second Set object not to "self". So still, your actual Set doesn't contains the given value.
return newSet // returns the value inserted Set object, not "self".
}
else {
let set: Set<String>? = [value]
return set
}
If we look at myTest() function you can see that your adding operation doesn't work on actual variable.
var set: Set<String>? = nil
set.myInsert("Hello") // at this point, myInsert function returns a new Set object with inserted given value. But this operation does not effect the original variable above. That means set variable is still nil
return set // returns nil variable.
I hope this helps.

Use Swift #propertyWrapper for dynamic default value?

I need a Swift property that -- if the value has not yet been set -- defaults to another value.
This can be implemented using backing-store private properties. For instance, for a property num that should default to a global defaultNum, it would work something like this:
var defaultNum = 1
class MyClass {
var num: Int {
get { _num ?? defaultNum }
set { _num = newValue }
}
private var _num: Int?
}
let c = MyClass()
print("initial \(c.num)") // == 1 ✅
// changing the default changes the value returned
defaultNum = 2
print("dynamic \(c.num)") // == 2 ✅
// once the property is set, returns the stored value
c.num = 5
print("base \(c.num)") // == 5 ✅
That works, but for a common pattern in our code, it's a lot of boilerplate for each such property.
Using Swift property wrappers, is it possible to do this more concisely?
What won't work
Note that, because we expect the default to be dynamic, static initializers will not work. For example:
var defaultNum = 1
class MyClass {
var num = defaultNum
}
var c = MyClass()
defaultNum = 2
print(c.num) // this == 1, we want the current value of defaultNum, which == 2
You can do this by creating a property wrapper like this:
#propertyWrapper
public struct Default<T> {
var baseValue: T?
var closure: () -> T
// this allows a nicer syntax for single variables...
public init(_ closure: #autoclosure #escaping () -> T) {
self.closure = closure
}
// ... and if we want to explicitly use a closure, we can.
public init(_ closure: #escaping () -> T) {
self.closure = closure
}
public var wrappedValue: T {
get { baseValue ?? closure() }
set { baseValue = newValue }
}
}
You then use the #Default property wrapper on a property like this:
var defaultNum = 1
class MyClass {
#Default(defaultNum)
var num: Int
}
You'd then see the following in practice:
let c = MyClass()
// if we haven't set the property yet, it uses the closure to return a default value
print("initial \(c.num)") // == 1 ✅
// because we are using a closure, changing the default changes the value returned
defaultNum = 2
print("dynamic \(c.num)") // == 2 ✅
// once the property is set, uses the stored base value
c.num = 5
print("base \(c.num)") // == 5 ✅

How to create higher order functions in Swift?

I have come across the array forEach function that is a higher order function and it takes only one parameter, i.e., a closure. Now this closure internally loops through all the elements of the array one by one but does not return anything. The implementation of the closure is left to the choice of the user.
I have a custom class MyClass that has a private variable inside it num and a public function setNum(num: Int) to set the value of that private variable from outside. I am just trying to create a similar function factorial inside my custom class that takes only one parameter, i.e., a closure. However, I have to manually call the closure inside factorial, pass the value of num as a parameter to the closure.
Is there a way that the closure can act on num without having passed it as a parameter? Basically I am just trying to replicate the array forEach function. Syntax of array forEach is:
array.forEach(body: (Int) -> Void) -> Void)
Implementation:
arr1.forEach { print($0) }
My code is as below:
import Foundation
public class MyClass {
private var factorialNumber: Double = 0
internal static var instance: MyClass?
public func setFactorialNumber(number value: Double) {
factorialNumber = value
}
public func factorial(body closure: (String?) -> Void) -> Void {
var outputString: String?
var result: Double = 1
if factorialNumber <= 0 {
outputString = nil
} else {
outputString = ""
while(factorialNumber >= 1) {
if factorialNumber == 1 {
outputString = outputString! + "\(factorialNumber) = \(result)"
break
} else {
outputString = outputString! + "\(factorialNumber) x "
}
result = result * factorialNumber
factorialNumber -= 1
}
}
// Finally closure call
closure(outputString)
}
private init() {}
public static func getInstance() -> MyClass {
if self.instance == nil {
self.instance = MyClass()
}
return self.instance!
}
}
And here is how I have to call my function to calculate the factorial:
var obj1 = MyClass.getInstance()
obj1.setFactorialNumber(number: 5)
obj1.factorial{ (result) in
print(result ?? "Factorial Result is Nil")
}
Please note that I have to pass a parameter result inside my closure to get the result of factorial.
Is there a way that the closure can act on num without having passed it as a parameter? Basically I am just trying to replicate the array forEach function ... [And, in your comment:] All I am trying to do is learn how to create higher order functions like array.forEach.
It's hard to understand what you think you're after, but taking you at your word, let's write forEach. Here we go:
extension Sequence {
func myForEach(f: (Element) -> ()) {
for e in self {
f(e)
}
}
}
Let's test it:
[1,2,3].myForEach { print($0) } // prints 1, then 2, then 3
We've done it! We wrote a higher-order function that acts exactly like forEach. So this must be how forEach actually works, more or less.
You can see from the example that it makes no sense to ask not to have to pass a parameter into the function that our forEach takes as a parameter. That is exactly what we must be able to do in order for that function to have an element to operate on.

Check if variable is a block / function / callable in Swift

Is there a simple and definite way in Swift to check whether something is a callable block / function? In some languages it's a trivial thing, but perhaps I'm looking at this from a wrong perspective in Swift? Consider the following.
func foo(){ print("foo") }
var bar: () -> () = { print("bar") }
var baz: () -> (Bool) = { print("baz"); return true }
print(foo) // (Function)
print(bar) // (Function)
print(baz) // (Function)
print(foo is () -> ()) // true
print(bar is () -> ()) // true
print(baz is () -> ()) // false
print(baz is () -> (Bool)) // true
Swift knows that they are all functions, though there is no such data type. I can check by using a solid signature, but there might be a situation where I don't care about the signature* and simply want to invoke it. For example:
func call(callable: () -> ()) {
callable()
}
call(foo) // foo
call(bar) // bar
call(baz) // error: cannot convert value of type '() -> (Bool)' to expected argument type '() -> ()'
I can rewrite it like this, which will work for Void and Bool return types, but doing this for every type is crazy, especially since I don't care about it, but compiler does…
func call(callable: Any) {
if let block: () -> () = callable as? () -> () {
block()
} else if let block: () -> (Bool) = callable as? () -> (Bool) {
block()
}
}
call(foo) // foo
call(bar) // bar
call(baz) // truely baz
* Agree, not caring about the signature is a sin. For the argument sake let's just not care about the return type.
You can check the String representation of .dynamicType of the callable for existence of substring ->. Not super-elegant, but it works:
func isAClosure<T>(foo: T) -> Bool {
return String(foo.dynamicType).containsString("->")
}
var a : () -> () = { print("Foobar") }
var b : (Double) -> (Bool) = { $0 > 0 }
var c : Int = 1
isAClosure(a) // true
isAClosure(b) // true
isAClosure(c) // false
Of course, as Marcus Rossel points out in the comment above, you still wouldn't know anything about the parameters of the callable (but perhaps that could be next step to find out, given that you know it's a callable).
Addition with regard to OPs questions below: just a technical discussion, and not recommended techniques.
You use the same approach as above to check if the function argument is a closure without arguments (() -> (...)) or one with neither arguments nor return type (() -> ()), and so on. Using this approach, you can define a generic function that call the argument sent to the function only if it is of a certain closure type. For this "in-function-call", you'll have to make use of type conversion to expected closure type, much as you've described in your Q above. It'll probably be difficult to circumvent this "non-generic" approach w.r.t. calling the closures. A few examples follow below.
/* Example functions */
func isAVoidParamClosure<T>(foo: T) -> Bool {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
return bar.count > 1 && (bar.first?.characters.count ?? 0) == 2
}
func callIfVoidVoidClosure<T>(foo: T) {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
if bar.count > 1 && !(bar.map{ $0 == "()" }.contains(false)) {
if let foo = foo as? () -> () {
foo()
}
}
}
func isASingleDoubleReturnTypeClosure<T>(foo: T) -> Bool {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
return bar.count > 1 && bar[1] == "Double"
/* rhs of '&&' lazily evaluated: [1] ok */
}
func printTwoTimesResultOfVoidDoubleClosure<T>(foo: T) {
if isAVoidParamClosure(foo) && isASingleDoubleReturnTypeClosure(foo) {
if let foo = foo as? () -> Double {
let a: Double = 2*foo()
print(a)
}
}
}
Example calls:
/* Example calls */
let a : () -> () = { print("Foobar") }
let b : (Double) -> (Bool) = { $0 > 0 }
let c : () -> Double = { 21.0 }
let d : Int = 1
isAVoidParamClosure(a) // true
isAVoidParamClosure(b) // false
isAVoidParamClosure(c) // true
isAVoidParamClosure(d) // false
callIfVoidVoidClosure(a) // Prints "Foobar"
callIfVoidVoidClosure(b)
callIfVoidVoidClosure(c)
callIfVoidVoidClosure(d)
printTwoTimesResultOfVoidDoubleClosure(a)
printTwoTimesResultOfVoidDoubleClosure(b) // Prints "42.0"
printTwoTimesResultOfVoidDoubleClosure(c)
printTwoTimesResultOfVoidDoubleClosure(d)

Variable used within its own initial value while variable is used inside a closure past init

typealias CBType = () -> Void
class A {
let b = B()
func test() {
let token = b.register { CBType in
self.b.waitFor([token]) // ERROR: Variable used within its own initial value
}
b.dispatch()
}
}
class B {
private var _callbacks = [String:CBType]()
func register(callback: CBType) -> String {
let id = "1234"
_callbacks[id] = callback
return id
}
func dispatch() {
for (_, cb) in self._callbacks {
cb()
}
}
func waitFor(tokens: [String]) {
}
}
A().test()
When I modify the test function to use a instance variable, things are working again but that syntax feels a bit heavy.
class A {
let b = B()
var token: String?
func test() {
token = b.register { CBType in
self.b.waitFor([self.token!])
}
b.dispatch()
}
}
Why can't I use a local variable in the closure since it will be way past initialization when the closure is finally called?
The constant token doesn't have a value at the time it is captured by the closure.
You can use a mutable variable instead, and the closure will capture the variable rather the its value.
func test() {
var token = ""
token = b.register {
self.b.waitFor([token])
}
b.dispatch()
}
Alternatively, you can pass the token as a parameter into the closure:
typealias CBType = (String) -> Void
class A {
let b = B()
func test() {
let token = b.register { theToken in
self.b.waitFor([theToken])
}
b.dispatch()
}
}
class B {
private var _callbacks = [String:CBType]()
func register(callback: CBType) -> String {
let id = "1234"
_callbacks[id] = callback
return id
}
func dispatch() {
for (id, cb) in self._callbacks {
cb(id)
}
}
func waitFor(tokens: [String]) {
println("Wait for \(tokens)")
}
}
A().test()
In your first example, token doesn't have a value when you make the call self.b.waitFor([token]).
In your second example, everything appears to work because by declaring token like so: var token: String? it is given an initial value (nil).
The issue isn't whether you are using an instance variable -vs- a local variable (or that it's being used within a closure), the issue is that (in the first example) you are trying to use the token within the expression that provides its initial value.
Equivalent to this would be declaring an Int like so: let myValue: Int = myValue + 1 - its initial value is supposed to be "what" + 1?