最近,我遇到了创建函数数组的需要。不幸的是,Swift语言没有为函数提供顶级类型,而是必须由其特定的签名(...)->(...)
声明它们。因此,我试图编写一个可以容纳任何函数的包装器,然后专门对其进行包装,使其仅容纳具有Void
返回类型和任意数量参数的闭包。
struct AnyFunction {
let function: Any
init?(_ object: Any){
switch String(describing: object){
case let function where function == "(Function)":
self.function = object
default:
return nil
}
}
func callAsFunction(){
self.function()
}
}
[在我前进的过程中,我发现它并不琐碎,并且可能需要进行一些自省的破解,但是尽管尝试了,但我仍未找到解决方案。编译器消息:
error: cannot call value of non-function type 'Any'
那么,您将如何弄清楚要定义一个可以容纳任何功能类型的对象的技巧?
说明:我希望定义如下内容:
typealias SelfSufficientClosure = (...)->Void
var a, b, c = 0
let funcs = FunctionSequence
.init(with: {print("Hi!")}, {a in a + 3}, {b in b + 3}, { a,b in c = a + b})
for f in funcs { f() }
print([a, b, c], separator: ",")
//outputs
//"Hi"
//3, 3, 6
PS此问题与此(Any or a trouble with sequence of functions)有关系
您可以使用枚举将各种函数放入数组,然后通过开关提取函数。
enum MyFuncs {
case Arity0 ( Void -> Void )
case Arity2 ( (Int, String) -> Void)
}
func someFunc(n:Int, S:String) { }
func boringFunc() {}
var funcs = Array<MyFuncs>()
funcs.append(MyFuncs.Arity0(boringFunc))
funcs.append( MyFuncs.Arity2(someFunc))
for f in funcs {
switch f {
case let .Arity0(f):
f() // call the function with no arguments
case let .Arity2(f):
f(2,"fred") // call the function with two args
}
}
函数是从输入到输出的映射。在您的示例中,您的输入无效(无输入),而您的输出也无效(无输出)。这样的功能正好是() -> Void
。
由于您的称呼,我们可以说这是正确的类型:
for f in funcs { f() }
您期望f
是一个不接受任何输入且不返回任何输出的函数,这正是() -> Void
的定义。通过使用该类型,我们可以准确获得您期望的输入和输出(并清除一些语法错误):
var a = 0, b = 0, c = 0
let funcs: [() -> Void] = [{print("Hi!")}, {a = a + 3}, { b = b + 3}, { c = a + b}]
for f in funcs { f() }
print(a, b, c, separator: ",")
//outputs
//Hi!
//3, 3, 6
[当您编写类似{a in a + 3}
的闭包时,这并不意味着“捕获a
”(我相信您是期望的)。这意味着“这是一个接受参数的闭包,该参数将称为a
(与同名的全局变量完全无关)并返回该值加3。”如果那是您的意思,那么当您调用f()
时,您需要传递它并使用返回值执行操作。