[swift-evolution] Swift should support generics as arguments to closures in any context

Spencer Kohan spencerkohan at gmail.com
Fri Jan 15 04:07:06 CST 2016


New here, hope I'm doing this right.

I recently found a use case which does not appear to be covered by the
swift language: it appears that there's no way to declare a closure type
with generic arguments.

For example, what if I'm building an iOS app, and I want to define a
closure which operates on UIViewControllers which implement a particular
protocol?

In ObjectiveC, this would be possible with the following syntax:

    typedef void (^MyBlockType)(UIViewController<MyProtocol>)

In Swift you can do this in the context of a function, class or struct:

    func myFunction<T: UIViewController where T:MyProtocol>() {
        let x : (T) -> () = { generic in
           ....
        }
    }

But what if you want to declare such a closure as a variable within the
protocol it's referring to?

    protocol MyProtocol {
        var protocolControllerCallback : (protocolController : ???? )->()
    }

It seems like Associated Types are the intended tool for this job, so you
could have something like:

    protocol MyProtocol {
        typealias ProtocolObservingController
        var protocolControllerCallback : (protocolController
: ProtocolObservingController )->() {get set}
    }

    class MyController : UIViewController, MyProtocol {
        typealias ProtocolObservingController = MyController
        ...
    }

But this doesn't quite solve the problem: we still can't have a closure
defined in this protocol which can operate on *any* implementations of the
protocol.  For instance, what if we wanted to pass a closure between two
different implementations?

    class MyChildController : UIViewController, MyProtocol {
        typealias ProtocolObservingController = MyChildController
        ...
    }

    class MyParentController : UIViewController, MyProtocol {
        typealias ProtocolObservingController = MyParentController
        ...

        func createChildController() -> MyControllerChild {
            let child = MyChildController()
            child.protocolControllerCallback =
self.protocolControllerCallback
        }

    }

It doesn't work because the types of protocolControllerCallback are
inconsistent between the two classes.

This feels like a hole in the language.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160115/f37b5bc4/attachment.html>


More information about the swift-evolution mailing list