【发布时间】:2022-07-27 00:09:47
【问题描述】:
我无法将以下函数编写为闭包
func myfunc<S where S: MyProtocol, S: MySuperClass>(param: S) { ... }
我试过了
let myClosure = {<S where S: MyProtocol, S: MySuperClass>(param: S) in ... }
,但它不起作用。
关于如何完成此操作的任何建议?
【问题讨论】:
标签: swift
我无法将以下函数编写为闭包
func myfunc<S where S: MyProtocol, S: MySuperClass>(param: S) { ... }
我试过了
let myClosure = {<S where S: MyProtocol, S: MySuperClass>(param: S) in ... }
,但它不起作用。
关于如何完成此操作的任何建议?
【问题讨论】:
标签: swift
我相信你要求的是没有意义的(与 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 目前似乎不支持泛型,所以 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 进行比较,我将其明确专门化为具体类型,然后可以构造。
【讨论】:
您可以尝试将闭包包装在声明泛型类型的结构中。就像是:
struct ClosureWrapper<S where S: MyClass, S: MyProtocol> {
let myClosure = {(param: S) in ... }
}
当然,此时你的闭包也可能是一个普通的函数 :P
【讨论】: