<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br></div><div>On Nov 16, 2016, at 16:35, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com">jordan_rose@apple.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 16, 2016, at 7:35, David Sweeris via swift-users &lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Nov 15, 2016, at 11:55 PM, Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com" class="">howard.lovatt@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">@Dave,<div class=""><br class=""></div><div class="">How do I write that though.</div><div class=""><br class=""></div><div class="">I can't write:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; extension Array: Equatable {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; static func ==(lhs: Array, rhs: Array) -&gt; Bool {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let size = lhs.count<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; precondition(rhs.count == size, "The arrays must be the same length")<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i in 0 ..&lt; size {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (lhs[i] as! Equatable) != (rhs[i] as! Equatable) {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true<br class="">&nbsp; &nbsp; &nbsp; &nbsp; }<br class="">&nbsp; &nbsp; }</div><div class=""><br class=""></div><div class="">Because I can't cast to an Equatable, because Equatable uses Self.</div><div class=""><br class=""></div><div class="">Am I missing something?</div><div class=""><br class=""></div><div class="">&nbsp;-- Howard.</div></div><div class="gmail_extra"><br clear="all" class=""><div class=""><div class="gmail_signature" data-smartmail="gmail_signature">&nbsp; -- Howard.<br class=""></div></div>
<br class=""><div class="gmail_quote">On 16 November 2016 at 16:35, David Sweeris <span dir="ltr" class="">&lt;<a href="mailto:davesweeris@mac.com" target="_blank" class="">davesweeris@mac.com</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br class="">
&gt; On Nov 15, 2016, at 21:39, Howard Lovatt via swift-users &lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>&gt; wrote:<br class="">
&gt;<br class="">
&gt; Hi All,<br class="">
&gt;<br class="">
&gt; Does anyone have a good workaround for generics not currently supporting conditional conformance to a protocol. As stated in the Generics Manifesto something like this would be nice:<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp;extension Array: Equatable where Element: Equatable {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;static func ==(lhs: Array, rhs: Array) -&gt; Bool { ... }<br class="">
&gt;&nbsp; &nbsp; &nbsp;}<br class="">
&gt;<br class="">
&gt; But I would currently write a wrapper, something like:<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; &nbsp;struct ArrayE&lt;T: Equatable&gt; {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var elements: [T]<br class="">
&gt;&nbsp; &nbsp; &nbsp;}<br class="">
&gt;&nbsp; &nbsp; &nbsp;extension ArrayE: Equatable {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;static func ==(lhs: ArrayE, rhs: ArrayE) -&gt; Bool { ...&nbsp; }<br class="">
&gt;&nbsp; &nbsp; &nbsp;}<br class="">
&gt;<br class="">
&gt; This can get unwieldy when there are a lot of conditional protocol extensions required, i.e. wrappers round wrappers.<br class="">
&gt;<br class="">
&gt; Is there a better way?<br class="">
&gt;<br class="">
&gt; Thanks for any tips,<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp;-- Howard.<br class="">
</div></div>&gt; ______________________________<wbr class="">_________________<br class="">
&gt; swift-users mailing list<br class="">
&gt; <a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><br class="">
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-users</a><br class="">
<br class="">
Can you make Array conform to Equatable for any T and then in the == function, if T conforms to Equatable loop the Arrays to check if they're equal, and if it doesn't conform just return false?<br class="">
<br class="">
I mean, it's still "wrong", but at least you won't get any false positives.<br class="">
<br class="">
- Dave Sweeris</blockquote></div><br class=""></div>
</div></blockquote><br class=""></div><div class="">You are correct. The work-around is to use two extensions and overload the == operator:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">Array</span><span style="font-variant-ligatures: no-common-ligatures;" class="">: </span><span style="font-variant-ligatures: no-common-ligatures" class="">Equatable</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">public</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">static</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> == (lhs: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Array</span><span style="font-variant-ligatures: no-common-ligatures" class="">, rhs: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Array</span><span style="font-variant-ligatures: no-common-ligatures" class="">) -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Bool</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(187, 44, 162);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">return</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">false</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; }</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Array</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Element : Equatable {</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">public</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">static</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> == (lhs: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Array</span><span style="font-variant-ligatures: no-common-ligatures" class="">, rhs: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Array</span><span style="font-variant-ligatures: no-common-ligatures" class="">) -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Bool</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> lhs.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">count</span><span style="font-variant-ligatures: no-common-ligatures" class=""> == rhs.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">count</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">&amp;&amp;</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">for</span><span style="font-variant-ligatures: no-common-ligatures" class=""> i </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span><span style="font-variant-ligatures: no-common-ligatures" class="">..&lt;lhs.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">count</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> lhs[i] != rhs[i] {</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">false</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">true</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; }()</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; }</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div></div>It works in playgrounds (Xcode 8.1 (8B62)), but I haven’t tested it outside a few trivial cases.</div></div></blockquote><br class=""></div><div>This does not work. The == dispatch for Arrays is static in this case, not dynamic. You can test this by writing something generic on Equatable.</div><div><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div>func same&lt;T: Equatable&gt;(_ x: T, _ y: T) -&gt; Bool { return x == y }</div><div>print(same([1], [2]))</div></blockquote><div class=""><br class=""></div>Rule of thumb: overloads are resolved statically, protocol requirements are invoked dynamically. You cannot get dynamic behavior out of just overloads, ever.<div class=""><br class=""></div><div class="">I don't think there's a way to get this behavior today, unfortunately.</div></blockquote><br><div>Aw, nuts! I forgot to try adding another level of, um... genericititty?</div><div><br></div><div>Yeah, I think you're right... On the plus side, when conditional conformance hits the wrapper structs can be backed out just by searching your project for their name and replacing it with "Array" (or "Set", etc), right?</div><div><br></div><div>- Dave Sweeris</div></body></html>