一尘不染

通过快速协议存储/传递功能类型

swift

以下代码使快速(3,3.1,4)编译器崩溃:

protocol Test {
    func f()
}
let x = Test.f // crash

我可能天真地希望编译器将其推断x为具有签名的Function Type (Test) -> (Void) -> Void,之后,我可以这样称呼它:

let y = SomeClassConformingToTest()
x(y)()

我想我的问题是:显然,编译器应该执行除崩溃以外的其他操作,但是Swift目前应该支持这种语法吗?


阅读 194

收藏
2020-07-07

共1个答案

一尘不染

如您所说,编译器永远不会崩溃;这确实是一个错误,已在此处提交。Swift团队成员Slava
Pestov在其中说:

我们计划使MyProtocol.someInstanceMethod工作。您已经可以在课程中执行此操作,例如,

class Foo {
    func f() { ... }
}
let f: Foo -> () -> () = Foo.f

它对于协议应该具有相同的行为:

protocol Foo {
    func f()
}
let f: Foo -> () -> () = Foo.f

我计划稍后再解决。

到2017年5月8日为止,该错误报告现已标记为“进行中”,因此希望可以将其纳入Swift 4.0的发行版中。

但是,在实现/修复之前,一个简单的解决方法是使用闭包表达式,以便对使用实例的方法进行部分应用来充当thunk:

protocol Test {
    func f()
}

struct S : Test {
    func f() {
        print("hello")
    }
}

let x: (Test) -> () -> Void = { $0.f }

let s = S()
x(s)() // "hello"

当然,如果不需要中间部分应用的函数,则可以说:

let x: (Test) -> Void = { $0.f() }

let s = S()
x(s) // "hello"
2020-07-07