[swift-evolution] protocol can only be used as a generic constraint because it has Self or associated type requirements

Dave Abrahams dabrahams at apple.com
Mon Dec 14 10:01:29 CST 2015


> On Dec 14, 2015, at 7:47 AM, Paul Cantrell <cantrell at pobox.com> wrote:
> 
>> On Dec 14, 2015, at 1:37 AM, Dave Abrahams <dabrahams at apple.com <mailto:dabrahams at apple.com>> wrote:
>> 
>>> func maxY(p1: P, p2: P) -> Int {
>>>   return max(p1.y, p2.y)   // No problems here!
>>> }
>>> 
>>> …right?
>> 
>> Ah, but then you have the situation that P doesn't conform to P (it doesn't have an x that you can access).  In my opinion that is just too weird an idea to be usable.
>> Personally, I have always thought that protocols intended to be used as unbound existentials (not P<A: Int>, just plain P) are different beasts entirely from the kind used as generic constraints and should be explicitly declared as such—I don't think I've ever seen a protocol that is well-used in both ways; if you have counterexamples I'd love to see them.  In "existential protocols," declaring an associated type or creating a self requirement would be an error at the point of declaration.  
> 
> IMHO, it’s an artificial distinction that makes sense only if you’re acclimated to Swift’s current behavior.
> 
> There are plenty of situations where you really do want a generic type in the protocol, but you nonetheless find yourself in situations where you care only about the parts of the protocol that don’t depend on that generic type.
> 
> Here’s an example, pared down a lot but taken from an actual project:
> 
>     protocol Request
>         {
>         typealias ContentType
>         
>         func onCompletion(callback: (ContentType?, ErrorType?) -> Void)
>         func onSuccess(callback: ContentType -> Void)
>         func onNewData(callback: ContentType -> Void)
>         func onFailure(callback: ErrorType -> Void)
>         
>         func cancel()
>         }
> 
>     struct RequestBatch
>         {
>         var requests: [Request]  // Sadness. Despair. DOOOOM.
>         
>         func cancelAll()
>             {
>             for request in requests
>                 { request.cancel() }
>             }
>         }
> 
> The current Swift solution is either to ditch the type safety of ContentType, or split Request into two protocols. The latter makes the API hard to read, and may decouple related protocol requirements that don’t make sense independently.

IMO the fact that you created an a array of requests and wrote cancelAll above *demonstrates* that the cancel requirement makes sense independently from the others.

-Dave



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151214/718d9f18/attachment-0001.html>


More information about the swift-evolution mailing list