<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><div id="AppleMailSignature"><span style="background-color: rgba(255, 255, 255, 0);">This is what I mean by diluting the semantics of these protocols. &nbsp;A type is not universally equatable, it is equatable with respect to values of its same type. &nbsp;Adding a generic is precisely an encoding of the former (even if this&nbsp;<i>particular</i>&nbsp;implementation says otherwise), our current implementation is an encoding of the latter. &nbsp;If you want to fix this, ask yourself: How is the typechecker supposed to know that you mean to include this extra "self-ness" constraint when you write e.g. Set&lt;Equatable&gt;?</span></div><div id="AppleMailSignature"><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div id="AppleMailSignature"><span style="background-color: rgba(255, 255, 255, 0);">As David mentioned, you may get some mileage out of existentials, but really only if you have a class hierarchy [Equatability will still come with constraints, even then]. &nbsp;You are absolutely right that your use-case is valid and I regret that you have to jump through hoops to ask for something that can be expressed so cleanly in the hypothetical. &nbsp;But until we have inference rules and/or syntax for this it's all just that.</span></div><br>~Robert Widmann</div><div><br>2016/06/29 0:05、Riley Testut &lt;<a href="mailto:rileytestut@gmail.com">rileytestut@gmail.com</a>&gt; のメッセージ:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><div class="">I do appreciate the thought out reply Robert! First, I do realize there are reasons *why* this is the case, my point is that we should re-evalutate these implementations so they’re no longer a reason :)</div><div class=""><br class=""></div><div class="">Secondly, for the Equatable protocol, I see two possible solutions. One would be to simply treat two types that do not belong to the same inheritance hierarchy as not equal (and is the approach I’ve taken in my own code). Here is a simplified example taken from my current project:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><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="">protocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> InputProtocol</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">/// Convenience method used for implementing Equatable. Default implementation via protocol extension</span></div><div style="margin: 0px; font-size: 11px; 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="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> isEqual&lt;T&gt;(</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> input: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</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></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">/// Provide default implementatation for InputProtocol.isEqual()</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(187, 44, 162);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">public</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">InputProtocol</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">where</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">Self</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">: Hashable</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">{</span></div><div style="margin: 0px; font-size: 11px; 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="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> isEqual&lt;T&gt;(</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> input: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</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></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; {</span></div><div style="margin: 0px; font-size: 11px; 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="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> input = input </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class="">? </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Self</span></div><div style="margin: 0px; font-size: 11px; 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; font-size: 11px; 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="">self</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">==</span><span style="font-variant-ligatures: no-common-ligatures" class=""> input</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><p style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</span><br class="webkit-block-placeholder"></p><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(187, 44, 162);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" 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; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">false</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div></div><div class=""><br class=""></div><div class=""><div class="">Now, I can compare any two InputProtocol types using the generic isEqual() method and it will do The Right Thing. However, an alternative approach is to simply be able to declare a == overload for a certain protocol like so:</div></div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">protocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> MyProtocol</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">{</span></div><div style="margin: 0px; font-size: 11px; 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="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> identifier: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">UUID</span><span style="font-variant-ligatures: no-common-ligatures" class=""> { </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">get</span><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> ==(lhs: </span><span style="font-variant-ligatures: no-common-ligatures" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">, rhs: </span><span style="font-variant-ligatures: no-common-ligatures" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">) -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Bool</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> { </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> lhs.</span><span style="font-variant-ligatures: no-common-ligatures" class="">identifier</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> == rhs.</span><span style="font-variant-ligatures: no-common-ligatures" class="">identifier</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> }</span></div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">The only downside to this method I see is that it could potentially be abused in a way to make two types that seemingly shouldn’t be equatable return true, such as conforming Int and String to MyProtocol above and both having the same identifier. Not sure how bad this would be in actual practice though (as in whether this would end up being a problem).</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">As for my specific use case, I’m developing a very modular, plug-in based application. Necessarily each plug-in effectively declares it’s own implementation of certain protocols, so unfortunately there’s no way to guarantee the application knows about all possible implementations at compile time.</span></div><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 29, 2016, at 1:49 AM, Robert Widmann &lt;<a href="mailto:devteam.codafi@gmail.com" class="">devteam.codafi@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class="">Yes, the restriction "sucks", but it is there for a reason. &nbsp;A protocol is not just a convenient collection of methods and properties you can generalize over, it's a contract. &nbsp;Each tells you something about what its implementers have to do before they can call themselves 'Equatable' or 'MyProtocol' etc. &nbsp;Let's see what happens at a very high level if we relax this constraint for Equatable as you have written here.</div><div class=""><br class=""></div><div class="">protocol Equatable {</div><div class="">&nbsp; func ==(_: Equatable, _: Equatable) -&gt; Bool</div><div class="">}</div><div class=""><br class=""></div><div class="">And now two implementers (implementation abbreviated for brevity)</div><div class=""><br class=""></div><div class="">extension String: Equatable {}</div><div class="">extension Int: Equatable {}</div><div class=""><br class=""></div><div class="">// ...</div><div class=""><br class=""></div><div class="">Given this definition, the following typecheck</div><div class=""><br class=""></div><div class="">1 == 2 // false</div><div class="">"A" == "A" // true</div><div class="">1 == "1" // ?</div><div class="">"ABC" == 123 // ?</div><div class=""><br class="">Being Equatable suddenly must include a component of self-identity. &nbsp;We have to be able to constrain the implementation to only those Equatable things that look like ourselves. &nbsp;Thus, Self constraints. &nbsp;Because 'MyProtocol' is not defining a protocol for things that understand equality, it is defining an equivalence relation over all possible implementations of ==, and that means that anything goes. &nbsp;</div><div class=""><br class=""></div><div class="">So you might modify this to use associated types then. &nbsp;What about an iteration that asks the implementer to specify the type made in the comparison?</div><div class=""><br class=""></div><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">protocol Equatable {</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; associatedtype Comparator</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; func ==(_: Equatable.Comparator, _: Equatable.Comparator) -&gt; Bool</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">This also solves nothing. &nbsp;You can't actually constrain the associated types here with a needed equality constraint. &nbsp;You can only push the problem down a needless level of abstraction.</span></div></div><div class=""><br class=""></div><div class="">Yes it's a pain to have to use Generics to reify restricted protocols. &nbsp;Yes it's a pain to give up use of protocol-ified collections. &nbsp;Yes it's not immediately obvious why these restrictions are in place. &nbsp;But to drop them would severely dilute the intended semantics and use of protocols that require knowledge of their reifications. &nbsp;Unfortunately, equality just happens to be one such protocol.</div><div class=""><br class=""></div><div class="">There are ways around this. &nbsp;If you have a sealed hierarchy you can write an enum that enumerates all possible implementations and delegates it's equatable conformance out to them. &nbsp;Often, identity can be found elsewhere in a type. &nbsp;For example, a hypothetical 'UUIDable' protocol could specify it's implementers produce a String UUID that could be stored in collections instead of UUIDable types themselves. &nbsp;For most other cases try to re-evaluate. &nbsp;Why do you need to generalize over this set of types in this way? &nbsp;Is there some other more generic way of handling this case?<br class=""><br class="">~Robert Widmann</div><div class=""><br class="">2016/06/28 23:17、Riley Testut via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; のメッセージ:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class="">Hello all,<div class=""><br class=""></div><div class="">If you’ve been (attempting) protocol-oriented development in your own projects, I’m sure you’ve come across a particular build error at one point:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">Protocol ‘MyProtocol' can only be used as a generic constraint because it has Self or associated type requirements<br class=""></blockquote><div class=""><br class=""></div><div class="">To be frank, this restriction in the current Swift model sucks, a lot. In *many* cases, this prevents me from using protocols, and instead I have to fall back to using concrete types.</div></div><div class=""><br class=""></div><div class="">Here are a couple examples of using protocols with collections that should work fine, but simply don’t:</div><div class=""><br class=""></div><div class=""><b class="">A Set of Types Conforming to Protocol</b></div><div class=""><b class=""><br class=""></b></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">protocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> MyProtocol: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Hashable&nbsp;</span>{}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> set = </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Set</span><span style="font-variant-ligatures: no-common-ligatures" class="">&lt;</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class="">&gt;()&nbsp;</span><span style="color: rgb(0, 132, 0);" class="">// ERROR: Protocol ‘MyProtocol' can only be used as a generic constraint because it has Self or associated type requirements</span></div></div><div class=""><b class=""><br class=""></b></div><div class="">When declaring a Set, the generic type of the Set’s contents must conform to Hashable. Following this, it would appear that you should be able to declare a Set containing types conforming to a given protocol which in turn conforms to Hashable. Nope! This also means you can’t have a Set&lt;Hashable&gt; (so no type-erased Sets for you!). One potential workaround is to use a box type, but if exposing the set to a user, this is essentially a leaky abstraction.</div><div class=""><br class=""></div><div class=""><b class="">Finding a Protocol Type Instance in an Array</b></div><div class=""><b class=""><br class=""></b></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">protocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp;{}</span></div></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> MyStruct: </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(79, 129, 135);" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> {}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> array = [</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class="">]()</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><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; color: #3d1d81" class="">append</span><span style="font-variant-ligatures: no-common-ligatures;" class="">(</span><span style="font-variant-ligatures: no-common-ligatures" class="">MyStruct</span><span style="font-variant-ligatures: no-common-ligatures;" class="">())</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> index = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">array</span><span style="font-variant-ligatures: no-common-ligatures" class="">.index(of: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyStruct</span><span style="font-variant-ligatures: no-common-ligatures" class="">())</span><span style="font-variant-ligatures: no-common-ligatures;" class="">&nbsp;</span><span style="color: rgb(0, 132, 0);" class="">// ERROR: Cannot invoke 'index' with an argument list of type '(of: MyStruct)'</span></div></div><div class=""><b class=""><br class=""></b></div><div class="">So, we can’t use Set as a collection for our protocol types, let’s use Array instead! Not so fast: because MyProtocol doesn’t conform to Equatable, we can’t use the Array.index(of:) function to find it. Easy fix though, just make MyProtocol conform to Equatable, right?</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">protocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> MyProtocol: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Equatable</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures" class=""> MyStruct: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> array = [</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class="">]()&nbsp;</span><span style="color: rgb(0, 132, 0);" class="">// ERROR: Protocol ‘MyProtocol' can only be used as a generic constraint because it has Self or associated type requirements</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><br class=""></div></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">Nope! Now that it conforms to Equatable, it can no longer be used in Array’s type declaration. However, there is a (somewhat) workaround for this problem:</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">protocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> MyProtocol {}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><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: #4f8187" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class="">, rhs: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyProtocol</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><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><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures" class=""> MyStruct: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> array = [</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class="">]()</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><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; color: #3d1d81" class="">append</span><span style="font-variant-ligatures: no-common-ligatures;" class="">(</span><span style="font-variant-ligatures: no-common-ligatures" class="">MyStruct</span><span style="font-variant-ligatures: no-common-ligatures;" class="">())</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> index = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">array</span><span style="font-variant-ligatures: no-common-ligatures" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">index</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="">: { $0 </span><span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">==</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">MyStruct</span><span style="font-variant-ligatures: no-common-ligatures" class="">() })</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-family: Menlo; font-size: 11px; font-variant-ligatures: no-common-ligatures;" class=""><span style="font-family: Helvetica; font-size: 12px;" class="">Basically, we can define the == function for MyProtocol, and then instead of using&nbsp;</span></span>Array.index(of:), we use&nbsp;Array.index(where:) to manually compare each item to see if it matches, aka what Array.index(of:) would do for us normally if we simply could declare MyProtocol as conforming to equatable.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><b class="">TL;DR</b></div><div style="margin: 0px; line-height: normal;" class="">Swift really pushes the idea of protocol-oriented programming, and for the most part this works well. However, due to some underlying restrictions in the current Swift model, you can’t use protocols in all the same places you can use concrete types, which sucks. This is especially confusing for beginners who are trying to use protocols, but get frustrated when it doesn’t work where they want it to (and don’t understand why), so they fall back to using concrete types (usually implemented with class inheritance). For this reason, I think these restrictions need to be fixed ASAP, or else the Swift language is essentially pushing people away from protocol-oriented programming.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">Riley Testut</div></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div></div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div></div></blockquote></div><br class=""></div></blockquote></body></html>