<div dir="ltr"><span style="font-size:12.8px">If I understand correctly, this still doesn't solve the problem exactly. Wouldn't Self in this context refer to the class that implements MyProtocol?</span><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">The example I raised is just a single use-case I ran into, but I think the more general point is that there isn't a good way to tell the compiler that a closure parameter must belong to more than one protocol, or a type plus a protocol.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Here's another (somewhat contrived) example:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Say I was writing an application like IMDB, and I had a protocol for directors and another for writers:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"> protocol Director {</div><div style="font-size:12.8px"> func directingCredits() -> [Film]</div><div style="font-size:12.8px"> }</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"> protocol Writer {</div><div style="font-size:12.8px"> func writingCredits() -> [Film]</div><div style="font-size:12.8px"> }</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">And I want to have a closure which returns all the movies written and directed by the same person:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"> var getWrittenAndDirectedFilms : (<Writer, Director>)->[Film] = { writerDirector in</div><div style="font-size:12.8px"> return writerDirector.writingCredits().filter { writerDirector.directingCredits().contains($0) }</div><div style="font-size:12.8px"> }</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Not all writers are directors, and not all directors are writers, but it's perfectly reasonable to have an operation which only works on objects which conform to those two protocols.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">It's easy to write a plain function that handles this use case using generics, but it's not possible with a closure. It seems like an unnecessary limitation. </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 15, 2016 at 6:01 PM, Félix Cloutier <span dir="ltr"><<a href="mailto:felixcca@yahoo.ca" target="_blank">felixcca@yahoo.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>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.</div><div><br></div>You can use Self in protocols, which refers to the implementing type:<div><br></div><div><div></div><blockquote type="cite"><div>protocol MyProtocol {</div><div><span style="white-space:pre-wrap">        </span>var protocolControllerCallback: Self -> Void { get }</div><div>}</div><div><br></div><div>class MyController: MyProtocol {</div><div><span style="white-space:pre-wrap">        </span>var protocolControllerCallback: MyController -> Void</div><div><span style="white-space:pre-wrap">        </span></div><div><span style="white-space:pre-wrap">        </span>init() {</div><div><span style="white-space:pre-wrap">                </span>protocolControllerCallback = { cnt in return }</div><div><span style="white-space:pre-wrap">        </span>}</div><div>}</div></blockquote><div><br></div>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.</div><div><div>
<br><span style="color:rgb(0,0,0);font-family:'Lucida Grande';font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;display:inline!important;float:none">Félix</span>
</div>
<br><div><blockquote type="cite"><div><div class="h5"><div>Le 15 janv. 2016 à 05:07:06, Spencer Kohan via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> a écrit :</div><br></div></div><div><div><div class="h5"><div dir="ltr">New here, hope I'm doing this right.
<div><br></div><div>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.</div><div><br></div><div>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?<br></div><div><br></div><div>In ObjectiveC, this would be possible with the following syntax:</div><div><br></div><div> typedef void (^MyBlockType)(UIViewController<MyProtocol>)</div><div><br></div><div>In Swift you can do this in the context of a function, class or struct:</div><div><br></div><div> func myFunction<T: UIViewController where T:MyProtocol>() {</div><div> let x : (T) -> () = { generic in</div><div> ....</div><div> }</div><div> }</div><div><br></div><div>But what if you want to declare such a closure as a variable within the protocol it's referring to?</div><div><br></div><div> protocol MyProtocol {</div><div> var protocolControllerCallback : (protocolController : ???? )->()</div><div> }</div><div><br></div><div>It seems like Associated Types are the intended tool for this job, so you could have something like:</div><div><br> protocol MyProtocol {</div><div> typealias ProtocolObservingController</div><div> var protocolControllerCallback : (protocolController : ProtocolObservingController )->() {get set}</div><div> }</div><div><br></div><div> class MyController : UIViewController, MyProtocol {</div><div> typealias ProtocolObservingController = MyController</div><div> ...</div><div> }</div><div><br></div><div>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?</div><div><br></div><div> class MyChildController : UIViewController, MyProtocol {</div><div> typealias ProtocolObservingController = MyChildController</div><div> ...</div><div> }</div><div><br></div><div><div> class MyParentController : UIViewController, MyProtocol {</div><div> typealias ProtocolObservingController = MyParentController</div><div> ...</div><div><br></div><div> func createChildController() -> MyControllerChild {</div><div> let child = MyChildController()</div><div> child.protocolControllerCallback = self.protocolControllerCallback</div><div> }</div><div><br></div><div> }</div></div><div><br></div><div>It doesn't work because the types of protocolControllerCallback are inconsistent between the two classes.</div><div><br></div><div>This feels like a hole in the language.</div><div><br></div><div><br></div><div><br></div><div><br></div></div>
</div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=iRI3beHTe3UxYAHTlV3lA38zIPfHMhyuRzgTmGKV6k4aCoAQZUIFePb7DSEP1BFSBFa9noVtcNSceUSF5Efg5XbsIaCciTuKiWCR55Hnalx0GWqOfNtwhoB5ANOQbZbR9xzfrar-2BDhMfMxXSUDFqwGr6ES6Ffsmjh-2FleexHeQ9JVGElR6plMfgPvpcnUNJ8vom76Oi5ThLNqg9pOb7LRIZd-2Bjo2rVbTKO1VIq4wHB9I-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br></div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Spencer Kohan<br>cell: 216 288 8258</div>
</div>