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

时间:2015-01-13 16:14:03

标签: swift overloading

假设我有一个功能:

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

然后,我将其称为:

test({$0 + $1 + $2 + $3})

是否可以在closureArgs内获得test的数量?目标是做超载。例如,test可能包含一些代码:

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

澄清 - 我的意思是我需要访问closureArgs的长度INSIDE test但是OUTSIDE closure

3 个答案:

答案 0 :(得分:2)

  

是否可以获得在测试中提供的closureArgs数量?

简答

没有

稍长答案

不,不是。原因如下:

该函数采用闭包作为它的参数,根据定义采用可变数量的参数。有人调用函数来指定闭包应该提前多少个参数。例如,如果我要调用你的函数,它可能看起来像这样:

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

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

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

答案 1 :(得分:1)

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

func test(c: (Double...) -> (Int, (Double...) -> Double)) {
    let (argCount, function): (Int, (Double...) -> Double) = { c($0) }()

    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

问题是,当你传递一个已经提供了参数的闭包(并且它需要知道如何计算计数的参数)时,你的闭包函数已经计算结果。因此,闭包返回它用于计算结果的参数数量以及结果。然后在test中,你可以使用参数的数量和结果。

我不知道......很难确切地知道你在追求什么,因为我不知道你知道参数的数量后你需要实现什么样的逻辑......

编辑:对不起,我一直在继续,但似乎你知道当你打电话给测试时会包含多少个参数,对吧?我的意思是,在你的例子中,你提供了4个参数:

test({$0 + $1 + $2 + $3})

(虽然,你真的需要重写为:

test({ return $0[0] + $0[1] + $0[2] + $0[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.
    }
}

现在,当您调用test时,只需将参数数量作为Int传递:

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

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

答案 2 :(得分:0)

答案可以追溯到Swift如何将参数传递给varargs函数,这是一个数组。一般来说,功能定义:

func takesVarArgs(args: Double...)

语法糖,为简单的调用提供了声明:

func takesVarArgs(args:[Double])

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

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

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

closureArgs.count