Storing/passing 来自 swift 协议的函数类型

Storing/passing Function Types from swift protocols

这段代码使 swift (3, 3.1, 4) 编译器崩溃:

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

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

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

我想我的问题是:显然编译器应该做一些事情而不是崩溃,但是 Swift 当前应该支持这种语法吗?

正如你所说,编译器永远不应该崩溃;这确实是一个错误,has been filed here。其中,Swift 团队的成员 Slava Pestov 说:

We plan on making MyProtocol.someInstanceMethod work. You can already do this for classes, eg,

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

It should have the same behavior for protocols:

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

I plan on addressing this later.

截至 2017 年 5 月 8 日的错误报告现在被标记为 "In Progress",因此希望这会进入 Swift 4.0 的发布版本。

但是,在 implemented/fixed 之前 – 一个简单的解决方法是使用闭包表达式作为方法的局部应用的 thunk 来调用它:

protocol Test {
    func f()
}

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

let x: (Test) -> () -> Void = { [=12=].f }

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

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

let x: (Test) -> Void = { [=13=].f() }

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