[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