在 Swift 中访问闭包中的参数数量

Accessing number of parameters in a closure in Swift

假设我有一个函数:

func test(closure: (closureArgs: Double ...) -> Double){
    //some logic
}

然后,我用它来调用它:

test({[=12=] +  +  + })

是否可以获取test内提供的closureArgs个数?目标是做超载。例如,test 可以包含一些代码,例如:

func test(closure: (closureArgs: Double ...) -> Double){
    //somehow get access to number of arguments in closureArgs within the closure that was passed.
}

澄清一下——我的意思是我需要在 test 内部访问 closureArgs 的长度,但在 closure

外部

答案可以追溯到 Swift 如何将参数作为数组传递给可变参数函数。一般来说,函数定义:

func takesVarArgs(args: Double...)

是语法糖,提供更简单的调用,用于声明:

func takesVarArgs(args:[Double])

因此,在您的情况下,您的闭包将被调用为:

func test(closure: (closureArgs:[Double]) -> Double)) -> Double

然后,在您的闭包中,您可以获得参数的数量:

closureArgs.count

我能想到的唯一方法是闭包 return 一个包含参数数量的元组和一个给出答案的函数,如下所示:

func test(c: (Double...) -> (Int, (Double...) -> Double)) {
    let (argCount, function): (Int, (Double...) -> Double) = { c([=10=]) }()

    switch argCount {
        // do something with function here
    }
}

func sum(a: Double...) -> (Int, ((Double...) -> Double)) { 
    return (a.count, { reduce(a, 0, +) })
}

类似的东西可能有用,但我不在可以测试它的地方。

编辑:我现在正在尝试对此进行测试,它已经很接近了,但是还没有用...

编辑:好的,这可行,但可能不是您想要的方式...

func test(c: (Int, Double)) {
    let (argCount, result) = c

    switch argCount {
        case 2:
            println("2 args were passed")
            println("The result was \(result)")
        default:
            println("nothing")
    }
}

func sum(a: Double...) -> (Int, Double) { 
    return (a.count, reduce(a, 0, +))
}

现在 test(sum(2, 4)) 将打印参数数量为 2,结果为 6

事实是,当你传递一个已经提供参数的闭包时(它需要参数来知道如何计算计数)那么你的闭包函数已经计算出一个结果。因此,闭包 return 用于计算结果的参数数量以及结果。然后在 test 中,您可以同时使用参数的数量和结果。

我不知道...很难确切地知道您在追求什么,因为一旦您知道了参数的数量,我就不确定您需要实现什么样的逻辑...

编辑:抱歉,我一直在继续,但您似乎知道调用测试时将包含多少参数,对吗?我的意思是,在您的示例中,您提供了 4 个参数:

test({[=12=] +  +  + })

(不过,您确实需要将其重写为:

test({ return [=13=][0] + [=13=][1] + [=13=][2] + [=13=][3] })

...因为记住,可变参数作为数组传递...)

因此,如果您知道将闭包传递给测试时将有多少参数,只需将参数的数量作为参数包含在测试中,如下所示:

func test(count: Int, closure: (Double...) -> Double) {

    switch count {
        case 1:
            // do what you want if there is only one argument
        case 2:
            // do what you want if there are two arguments...etc.
    }
}

现在调用测试时,只需将参数数量作为 Int:

test(4, { return [=15=][0] + [=15=][1] + [=15=][2] + [=15=][3] })

换句话说,你总是知道在传递给闭包时传递了多少参数。如果您想让 test 知道,只需将其作为参数包含在内即可。

Is it possible to get the number of closureArgs provided within test?

简短的回答

没有

稍微长一点的答案

不,不是。原因如下:

该函数采用闭包,因为它的参数根据定义采用可变数量的参数。调用函数的人无法提前指定闭包应采用的参数数量。例如,如果我要调用您的函数,它可能如下所示:

test() { (closureArgs: Double...) -> Double in
    var n: Double = 0
    for i in closureArgs {
        n += i
    }
    return n
}

您会注意到,我没有在任何地方定义参数的数量,因为参数的数量仅在调用闭包时指定。然后可以在内部确定该数字,或者可能返回该数字。

基本上,闭包是在测试中调用的,所以只有调用者知道它需要多少参数。任何使用此功能的人都无法控制它。