[swift-evolution] Swift should support generics as arguments to closures in any context
Félix Cloutier
felixcca at yahoo.ca
Fri Jan 15 11:01:11 CST 2016
Are you sure that your problem is about generics on lambdas? Seems to me that you wouldn't need generic lambdas if you could solve your initial problem in a different way.
You can use Self in protocols, which refers to the implementing type:
> protocol MyProtocol {
> var protocolControllerCallback: Self -> Void { get }
> }
>
> class MyController: MyProtocol {
> var protocolControllerCallback: MyController -> Void
>
> init() {
> protocolControllerCallback = { cnt in return }
> }
> }
That doesn't work right now because Swift will complain that the class must be `final` for reasons that sound bogus to me: "it uses 'Self' in a non-parameter, non-result type position". I don't know if there's a technical reason that it can't be in a closure parameter. Still seems to get you closer to what you want.
Félix
> Le 15 janv. 2016 à 05:07:06, Spencer Kohan via swift-evolution <swift-evolution at swift.org> a écrit :
>
> 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.
>
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160115/20844f2c/attachment.html>
More information about the swift-evolution
mailing list