一尘不染

泛型作为快速关闭的参数

swift

我在编写以下函数作为闭包时遇到麻烦

func myfunc<S where S: MyProtocol, S: MySuperClass>(param: S) { ... }

我试过了

let myClosure = {<S where S: MyProtocol, S: MySuperClass>(param: S) in ... }

但这不起作用。

有什么建议?


阅读 210

收藏
2020-07-07

共1个答案

一尘不染

我相信您要的东西没有任何意义(与Swift无关)。尽管我有兴趣证明自己是错误的,但我不认为可以用任何强类型语言合理地创建它。(编辑:继续我的研究,我相信使用一流的多态性的语言是可行的,但我不知道实际上有此功能的任何通用语言。)

let myClosure = {<S where S: MyProtocol, S: MySuperClass>(param: S) in ... }

您希望myClosure是哪种类型?泛型创建抽象类型。除非专业化,否则它不会成为真实类型。因此myClosure本身就是抽象类型。这就像要求一个抽象类的实例。“抽象”的全部要点是您无法构建一个。您可能会说的最好的一点是,myClosure它本身就是一种您需要实例化为真实实例的类型(但随后let没有任何意义;您不进行输入let)。

当您将其包装在中时struct,您真正要做的是创建一个抽象类型,当您创建实例时,它将专门化为实型。

现在,IMO(但目前看来是不可能的)有意义的是:

typealias Mapping<S> = S -> S
let identity: Mapping<Int> = { return $0 }

这是有道理的,因为您要定义一个抽象类型(Mapping),然后实例化一个具体类型Mapping<Int>。不幸的是,typealias目前似乎还不支持泛型,因此a
struct可能是我们拥有的最好的工具。


请注意,虽然typealias是半身像,但显然可以对函数变量本身进行专门化处理。我知道这不是闭包,但在某些情况下可能有用。

func Identity<T>(i:T) -> T {
  return i
}

let identityInt:(Int -> Int) = Identity
identityInt(1) // => 1

使用此方法进一步探讨抽象类型的问题,请考虑:

func Identity<T>(i:T) -> T { return i }
let x = Identity

这无法编译并显示以下错误:

error: cannot convert the expression's type '(T) -> T' to type '(T) -> T'

那是因为类型(T) -> T不是具体类型,所以您不能有一个叫做的类型x。与进行比较,identityInt我明确将其专门化为具体类型,然后可以进行构造。

2020-07-07