是否可以调用 Any 的 callAsFunction() 变量?
Is is possible to callAsFunction() variable that is Any?
最近遇到了创建函数数组的需求。不幸的是,Swift 语言没有为函数提供顶级类型,而是必须通过它们的特定签名 (...)->(...)
来声明它们。所以我尝试编写一个可以容纳任何函数的包装器,然后将其专门化以仅容纳具有 Void
return 类型和任意数量参数的闭包。
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这个问题与这个问题有关()
您可以使用枚举将各种函数放入数组中,然后使用开关提取函数。
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
是一个没有输入且 return 没有输出的函数,这正是 () -> 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}
这样的闭包时,这并不意味着 "capture a
"(我相信你在期待)。这意味着 "This is a closure that accepts a parameter that will be called a
(completely unrelated to the global variable of the same name) and returns that value plus 3." 如果那是你的意思,那么当你调用 f()
时,你需要传递一些东西并用 return 值做一些事情。
最近遇到了创建函数数组的需求。不幸的是,Swift 语言没有为函数提供顶级类型,而是必须通过它们的特定签名 (...)->(...)
来声明它们。所以我尝试编写一个可以容纳任何函数的包装器,然后将其专门化以仅容纳具有 Void
return 类型和任意数量参数的闭包。
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这个问题与这个问题有关(
您可以使用枚举将各种函数放入数组中,然后使用开关提取函数。
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
是一个没有输入且 return 没有输出的函数,这正是 () -> 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}
这样的闭包时,这并不意味着 "capture a
"(我相信你在期待)。这意味着 "This is a closure that accepts a parameter that will be called a
(completely unrelated to the global variable of the same name) and returns that value plus 3." 如果那是你的意思,那么当你调用 f()
时,你需要传递一些东西并用 return 值做一些事情。