是否可以调用 Any 的 AsFunction() 变量?



最近我遇到了创建函数数组的需求。不幸的是,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])
//outputs 
//"Hi"
//3, 3, 6

PS这个问题与这个问题有关(任何或功能序列的问题(

函数是从输入到输出的映射。在您的示例中,您的输入为 void(无输入(,您的输出也是 void(无输出(。所以这种功能正是() -> 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()时,你需要传递一些东西并对返回值做一些事情。

您可以使用枚举将各种函数放入数组中,然后使用开关提取函数。

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
}
}

相关内容

  • 没有找到相关文章

最新更新