如何有条件地调用任意swift函数(没有if块)

rxztt3cl  于 2023-01-16  发布在  Swift
关注(0)|答案(2)|浏览(172)

我想写一个通用的Swift函数,它有以下简单的用途:

  • 将任何函数作为参数
  • 采用布尔参数
  • 如果bool参数为TRUE,则用它的参数调用输入函数。否则为No-op。

其目的是消除代码中满足特定条件的大量笨拙的if语句。
比如:

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

但是,我正在努力找到语法,使参数能够传递给输入myFunc() func。
这个例子非常基本,我的输入函数闭包可以接受和发出任何类型的输入/输出,包括结构体、类和objective c的东西。
我有一种预感,这是可能的,通过一个机制称为函数对象,但我不是很熟悉它。
我应该重新发明轮子吗,或者已经有一个库/已知的方法成功地做到了这一点,而我却错过了?

jdgnovmf

jdgnovmf1#

我不知道你为什么认为

invokeIfConditionIsTrue(testIntToInt, condition)

在某种程度上上级

if condition { result = testIntToInt(n) }

或者

result = condition ? testIntToInt(n) : 0

但是你想要的几乎是不可能的,除非你把函数 Package 在一个闭包中,因为在Swift中没有办法把“带有任何参数的函数”表达为一个类型。你能做的最好的事情就是把你的函数 Package 在一个带有已知参数类型的闭包中。也没有通用的Closure类型来表示任何闭包。

func invokeIfConditionIsTrue(closure: () -> (), condition: Bool) {
    if condition {
        closure()
        print("executed")
    }
}

invokeIfConditionIsTrue(closure: { result = testIntToInt(n) }, condition: true)

但是,正如您所看到的,这并不比if语句好多少,事实上,它要糟糕得多。
另一种可能性是定义一个返回函数的函数,但它仍然需要知道参数类型。

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)
hxzsmxv2

hxzsmxv22#

经过一番讨价还价和寻找语法(正如我在开头提到的,我不擅长FP),我能够在我的XCode 14.2操场上编译并运行下面的解决方案。

    • 我想要的功能:**
func executeIfCondition(function: (@escaping (Any...) -> Any), condition: Bool) {
    if condition {
        function()
    }
}

这是为了替换我的代码库中的以下类型的调用:

if condition {
    function()
}

测试要调用的函数,如果condition = true,则使用executeIfCondition

func printStringAndReturnInt(i: Int, s: String) -> Int {
    print(s)
    return i
}

func printInt(i: Int) -> Void {
    print("\(i)")
}

func printArray(arr: [Int]) -> Void {
    arr.forEach({ print("\($0)") })
}

struct Struct1 {
    var value1: Int
    var value2: Int
}

func printStruct(t: Struct1) {
    print("Struct1: \(t.value1) - \(t.value2)")
}

class Class1 {
    var value1: Double = 100.0
    var value2: Double = 200.0
}

func printClass(c: Class1) {
    print("Class1: \(c.value1) - \(c.value2)")
}
    • 示例用法:**

取代:

if (true) {
    printStringAndReturnInt(i: 5, s: "Wow!")
}

我现在将使用:

executeIfCondition(function: { _ in printStringAndReturnInt(i: 5, s: "Wow!") }, condition: true)
    • 其余**
executeIfCondition(function: { _ in printInt(i: 61) }, condition: false)
executeIfCondition(function: { _ in printArray(arr:[9,10,11,12]) }, condition: true)
executeIfCondition(function: { _ in printStruct(t: Struct1(value1: 100, value2: 200)) }, condition: true)
executeIfCondition(function: { _ in printClass(c: Class1()) }, condition: true)

这还不是详尽无遗的,但足以作为一个开始。

相关问题