【问题标题】:Closure with generic parameters带有泛型参数的闭包
【发布时间】: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


    【解决方案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&lt;Int&gt;。不幸的是,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) -&gt; T 不是具体类型,所以你不能有一个名为x 的类型。将其与 identityInt 进行比较,我将其明确专门化为具体类型,然后可以构造。

    【讨论】:

    • 我相信你是对的 :) 谢谢你非常详尽的回答
    • Haskell 是一种支持这种多态性的强类型通用语言。
    【解决方案2】:

    您可以尝试将闭包包装在声明泛型类型的结构中。就像是:

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

    当然,此时你的闭包也可能是一个普通的函数 :P

    【讨论】:

    • 我最终得到了一个类似的解决方案,在结构上创建了一个静态函数,但感觉更像是一种解决方法。虽然不知道你可以把泛型放在结构定义中 :D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    相关资源
    最近更新 更多