在 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
}
您会注意到,我没有在任何地方定义参数的数量,因为参数的数量仅在调用闭包时指定。然后可以在内部确定该数字,或者可能返回该数字。
基本上,闭包是在测试中调用的,所以只有调用者知道它需要多少参数。任何使用此功能的人都无法控制它。
假设我有一个函数:
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
}
您会注意到,我没有在任何地方定义参数的数量,因为参数的数量仅在调用闭包时指定。然后可以在内部确定该数字,或者可能返回该数字。
基本上,闭包是在测试中调用的,所以只有调用者知道它需要多少参数。任何使用此功能的人都无法控制它。