I want to write a general-purpose Swift function that serves the following simple purpose:
The purpose is to eliminate a lot of clumsy if
statements in the code that meet a specific criteria.
Something like:
typealias ClosureType = (Any...) -> Any. // Notice the variable argument of any kind
func invokeIfConditionIsTrue(closure: Closure, condition: Bool) {
if condition {
if let myFunc = closure as? ClosureType {
myFunc()
print("executed")
} else {
print("not executed")
}
}
}
func testIntToInt(i: Int) -> Int {
return i*i
}
func testIntToDouble(i: Int) -> Double {
return Double(i*i)
}
invokeIfConditionIsTrue(testIntToInt, true). // executed
invokeIfConditionIsTrue(testIntToDouble, false). // not executed
However, I am struggling to come up with syntax that will enable the argument passing to the input myFunc()
func.
The example is pretty basic, and my input function closure could be accepting and emitting any type of input/outputs, including structs, classes and objective c stuff.
I have a hunch this is possible via a mechanism called function object, but I am not familiar enough with it.
Should I reinvent the wheel, or is there already a library/known way which is doing it successfully, and I am missing out?
I have no idea why you think
invokeIfConditionIsTrue(testIntToInt, condition)
is somehow superior to
if condition { result = testIntToInt(n) }
Or
result = condition ? testIntToInt(n) : 0
but what you want is pretty much impossible unless you wrap the function in a closure because there is no way to express "function with any arguments" in Swift as a type. The best you can do is wrap your function in a closure with known argument types. There's also no general Closure
type that represents any closure.
func invokeIfConditionIsTrue(closure: () -> (), condition: Bool) {
if condition {
closure()
print("executed")
}
}
invokeIfConditionIsTrue(closure: { result = testIntToInt(n) }, condition: true)
But, as you can see, that's not really any better than an if
statement. In fact, it's much worse.
Another possibility is to define a function that returns a function, but it still needs to know the argument types.
func invokeIfConditionIsTrue(closure: (Int) -> Int, condition: Bool) -> (Int) -> Int?
{
if condition {
return closure
}
else
{
return { _ in 0 } // A dummy function
}
}
invokeConditionIfTrue(closure: testIntToInt, condition: true)(n)