<div dir="ltr">Isn&#39;t this issue related to what Kotlin tries to solve with in/out variances (and star-projection)?<div><a href="https://kotlinlang.org/docs/reference/generics.html">https://kotlinlang.org/docs/reference/generics.html</a><br></div><div><br></div><div>Btw. what was the reason again that protocols use a typealias syntax instead of &quot;protocol Protocol&lt;T&gt;&quot;?</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 14, 2015 at 4:47 PM, Paul Cantrell via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</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"><span class=""><blockquote type="cite">On Dec 14, 2015, at 1:37 AM, Dave Abrahams &lt;<a href="mailto:dabrahams@apple.com" target="_blank">dabrahams@apple.com</a>&gt; wrote:</blockquote><blockquote type="cite"><br></blockquote></span><blockquote type="cite"><span class=""><div><blockquote type="cite" style="font-family:HelveticaNeue"><div><div style="word-wrap:break-word"><div><div style="word-wrap:break-word"><div>func maxY(p1: P, p2: P) -&gt; Int {</div><div>  return max(p1.y, p2.y)   // No problems here!</div><div>}</div></div><div><div style="word-wrap:break-word"><div><br></div><div>…right?</div></div></div></div></div></div></blockquote><br style="font-family:HelveticaNeue"></div></span><span class=""><div><div>Ah, but then you have the situation that P doesn&#39;t conform to P (it doesn&#39;t have an x that you can access).  In my opinion that is just too weird an idea to be usable.</div><div>Personally, I have always thought that protocols intended to be used as unbound existentials (not P&lt;A: Int&gt;, just plain P) are different beasts entirely from the kind used as generic constraints and should be explicitly declared as such—I don&#39;t think I&#39;ve ever seen a protocol that is well-used in both ways; if you have counterexamples I&#39;d love to see them.  In &quot;existential protocols,&quot; declaring an associated type or creating a self requirement would be an error at the point of declaration.  </div></div></span></blockquote><div><br></div><div>IMHO, it’s an artificial distinction that makes sense only if you’re acclimated to Swift’s current behavior.</div><div><br></div><div>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.</div><div><br></div><div>Here’s an example, pared down a lot but taken from an actual project:</div><div><br></div><div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">    <span style="color:#323e7d">protocol</span> Request</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        {</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:#323e7d">typealias</span> ContentType</div><p style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px">        <br></p><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:rgb(50,62,125)">func</span> onCompletion(callback: (<span style="color:rgb(88,126,168)">ContentType?, ErrorType?)</span> -&gt; <span style="color:rgb(88,126,168)">Void</span>)</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:#323e7d">func</span> onSuccess(callback: <span style="color:#587ea8">ContentType</span> -&gt; <span style="color:#587ea8">Void</span>)</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:rgb(50,62,125)">func</span> onNewData(callback: <span style="color:rgb(88,126,168)">ContentType</span> -&gt; <span style="color:rgb(88,126,168)">Void</span>)</div><p style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px"><span style="font-size:10.5px">        </span><span style="font-size:10.5px;color:rgb(50,62,125)">func</span><span style="font-size:10.5px"> onFailure(callback: </span><span style="font-size:10.5px;color:rgb(88,126,168)">ErrorType</span><span style="font-size:10.5px"> -&gt; </span><span style="font-size:10.5px;color:rgb(88,126,168)">Void</span><span style="font-size:10.5px">)</span></p><p style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px">        <br></p><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:#323e7d">func</span> cancel()</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        }</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px"><br></div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">    <span style="color:#323e7d">struct</span> RequestBatch</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        {</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:#323e7d">var</span> requests: [<span style="color:#587ea8">Request</span>]  <font color="#901000">// Sadness. Despair. DOOOOM.</font></div><p style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px">        <br></p><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:#323e7d">func</span> cancelAll()</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">            {</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">            <span style="color:#323e7d">for</span> request <span style="color:#323e7d">in</span> <span style="color:#587ea8">requests</span></div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">                { request.<span style="color:#587ea8">cancel</span>() }</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">            }</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        }</div></div><div><br></div><div>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.</div><span class=""><br><div><blockquote type="cite"><div>On Dec 14, 2015, at 1:40 AM, ilya &lt;<a href="mailto:ilya.nikokoshev@gmail.com" target="_blank">ilya.nikokoshev@gmail.com</a>&gt; wrote:</div><br><div><div dir="ltr" style="font-family:HelveticaNeue">You can achieve the same result more cleanly with <div><br></div><div><div>func maxY&lt;T:P, U:P&gt;(p1:T, p2: U) -&gt; Int {</div><div>  return max(p1.y, p2.y)   // No problems here!</div><div>}</div></div></div></div></blockquote><br></div></span><div>True, but this doesn’t generalize to other contexts, e.g. RequestBatch.requests above.</div><div><br></div><div>Conceptually, at least to me, a protocol describes a set of related capabilities that together add up to a meaningful behavior. Whether some of those capabilities share a generic type is incidental, and does not fundamentally change the nature of a protocol. Protocols should be protocols.</div><div><br></div><div>Java can do this via the &lt;?&gt; syntax:</div><div><br></div><div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;color:rgb(88,126,168)"><span style="color:#000000">    interface </span>Request<span style="color:#000000">&lt;</span>ContentType<span style="color:#000000">&gt;</span></div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        {</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        void onCompletion(CompletionCallback&lt;ContentType&gt; callback);</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        void onSuccess(SuccessCallback&lt;ContentType&gt; callback);</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        void onNewData(SuccessCallback&lt;ContentType&gt; callback);</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        void onFailure(FailureCallback&lt;ContentType&gt; callback);</div><p style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px">        <br></p><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        void cancel();</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        }</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px"><br></div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">    <span style="color:#323e7d">class</span> RequestBatch</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        {</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:#323e7d">private</span> List&lt;Request&lt;?&gt;&gt; requests;</div><p style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo;min-height:12px">        <br></p><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        <span style="color:#323e7d">public</span> void cancelAll()</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">            {</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">            <span style="color:#323e7d">for</span>(Request&lt;?&gt; request: requests)</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">                { request.cancel(); }</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">            }</div><div style="margin:0px;font-size:10.5px;line-height:normal;font-family:Menlo">        }</div><div><br></div></div><div>And yes, “Java can do it” is a deliberate provocation! :P</div><div><br></div><div>Cheers,</div><div><br></div><div>Paul</div><div><br></div><div>
<div style="color:rgb(0,0,0);letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wrap:break-word"><span style="border-collapse:separate;border-spacing:0px;line-height:normal"><div style="word-wrap:break-word"><span style="border-collapse:separate;border-spacing:0px;color:rgb(0,0,0);font-family:&#39;Helvetica Neue&#39;;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="border-collapse:separate;border-spacing:0px;color:rgb(0,0,0);font-family:&#39;Helvetica Neue&#39;;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––<br><a href="https://innig.net" target="_blank">https://innig.net</a> • @inthehands • <a href="http://siestaframework.com/" target="_blank">http://siestaframework.com/</a><br><br></span></span></div></span></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=6ZGE61OxINd5lLe2xYh9Ku-2BXbixWNr2nvfzp2IB1sZiiAmxhC9-2BZNg7mOAfk-2F2bif9BGdOdU0G1H1zoi-2Bvpt-2F86Roy52cVzaxUpd7xzBWKsptnBBhnFwjPiOTpLSR7XbZ0-2FwecVFGA4WTQ4jf6GTmerdRwrewg4rg0H7E7iV1VwX89qQKTFhliYXjcmPKq-2FYV74qdzRCn-2FFNpXpdvkGKT76gjH7KSqihLP9-2Btj622B4-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">
</div>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>