<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 22, 2016, at 9:36 AM, Maximilian Hünenberger &lt;<a href="mailto:m.huenenberger@me.com" class="">m.huenenberger@me.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="Apple-interchange-newline">Am 22.01.2016 um 03:05 schrieb David Waite &lt;<a href="mailto:david@alkaline-solutions.com" class="">david@alkaline-solutions.com</a>&gt;:<br class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Since Hashable is only self constrained due to Equatable should we even allow this code?</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">let a: Equatable = 1</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">let b: Equatable = "2"</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">a == b</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">// in this case there could be a more general == function</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">func == &lt;T: Equatable, U: Equatable&gt;(x: T, y: U) -&gt; Bool {</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">&nbsp; &nbsp; if let yAsT = y as? T {</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; return yAsT == x }</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">&nbsp; &nbsp; return false</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">}</div></div></blockquote><div><br class=""></div>That is fun code :-) But I don’t understand what it has to do with Hashable</div><div><br class=""></div><div>Since today equatable mandates a defined, public == method, and I think the generic is always loses to that specificity. You don’t even need dynamic casting, because your generic version only gets called when there isn’t a non-generic version.</div><div><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div><div class="">// in this case there could be a more general == function</div></div></div><div><div><div class="">func == &lt;T: Equatable, U: Equatable&gt;(x: T, y: U) -&gt; Bool {</div></div></div><div><div><div class="">&nbsp; &nbsp; return false</div></div></div><div><div><div class="">}</div></div></div></blockquote><div><div><div class=""><div class=""><br class=""></div></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div>1 == 1 // true</div><div>1 == “1” // false</div></blockquote><div><br class=""></div><div>Swift doesn’t seem to fight as hard as other languages against overloads that may be ambiguous in some contexts (for instance, two methods identical except for different return types). The flexibility of the compiler in interpreting code is one of the reasons that implicit conversions (such as with optionals or objective C bridging types) can lead to such confusing behavior in code. Most recent case to blow my mind,</div><div><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div>let a = [[1]]</div><div>a == a // error:&nbsp;binary operator '==' cannot be applied to two '[Array&lt;Int&gt;]' operands</div><div class=""><br class=""></div>import Foundation<div class=""><br class=""></div><div class="">a == a //&nbsp;$R2: Bool = true</div><div class=""><br class=""></div></blockquote>This works because the compiler promotes [[1]] to either [NSArray] or an NSArray outright to get to a working == operator.<div class=""><div><br class=""></div><div><br class=""></div><div><div><blockquote type="cite" class=""><div class="">But it seems like that there has to be a different implementation of `self` constrained functions (like ==) if a self constrained protocol is used without specifying `self`.</div></blockquote><div class=""><div class=""><br class=""></div></div><div class="">Thats what we mean by opening the type - exposing enough of the dynamic type information to the calling context such that we can safely expose methods. E.g. Something like this would be equivalent to your earlier fun code, except now the call site of the function is not generically constrained:</div><div class=""><br class=""></div><div class="">let a:Equatable = 1</div><div class="">let b:Equatable = “1”</div><div class=""><br class=""></div><div class="">func ==(lhs:Equatable, rhs:Equatable) -&gt; Bool {</div><div class="">&nbsp; &nbsp; typealias T = lhs.dynamicType</div><div class="">&nbsp; &nbsp; let x = lhs as! T</div><div class="">&nbsp; &nbsp; if let y = rhs as? T {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return x == y</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; return false</div><div class="">}</div><div class=""><br class=""></div><div class="">a == b // false</div><div class=""><br class=""></div></div><blockquote type="cite" class=""><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class="">Protocols would not have a simplistic order to implement (for example, I could be extending two parent protocols, both with their own associated types)</div><div class=""><br class=""></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Do you mean conforming to a protocol by "extending"?</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">In this case it would be even more explicit about types:</div></div></blockquote><div><br class=""></div><div><br class=""></div><div>Sorry, I used Java parlance where interfaces can extend other interfaces to add additional requirements/exposed capabilities.</div><div><br class=""></div>The specific example I had in mind is CollectionType, which inherits from both SequenceType and Indexable. Would Index come before or after Generator and SubSequence if you were positionally declaring arguments. Should swapping the inheritance order on CollectionType be a fragile change?</div><div><br class=""></div><div><br class=""></div><div><blockquote type="cite" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">To be clear, I'm proposing:</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">- Generic syntax for all types including protocols to be the same</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">- Named generic parameters eg: Array&lt;Element: Int&gt; &nbsp;, &nbsp;CollectionType&lt;Element: String, Index: Int&gt;</div></blockquote><div><br class=""></div><div>I’m not a fan of this syntax, because in an example where clause “where Element:Number" is a covariant constraint, and here (I think) you are using it as an invariant constraint. This seems confusing unless you specify Array&lt;Element == Int&gt;, etc.</div><div><br class=""></div><div>You have the issue today that SequenceType does not expose Element but Generator. This kind of relationship can’t be expressed without a ‘where’ type syntax. I did sketch out a version of SequenceType that uses Element explicitly, so I assume this is what you are basing on. Still, such design can’t be assumed universal.</div><div><br class=""></div><blockquote type="cite" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">- Without name:<span class="Apple-converted-space">&nbsp;</span><span style="background-color: rgba(255, 255, 255, 0);" class="">Array&lt;Int&gt; &nbsp;, &nbsp;CollectionType&lt;String, Int&gt;</span></div></blockquote>I already pointed out the CollectionType issue with positional arguments above. In addition, SequenceType will have an associated type of SubSequence, which I assume you are assuming would be the third argument and are implicitly stating “don’t care”.</div><div><br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class=""><div class=""><div class=""><div class=""><font class=""><span class="" style="background-color: rgba(255, 255, 255, 0);">I personally think there is a bit too much overlap between ‘where’ syntax, and possibly conflicting usage.&nbsp;</span></font><span class="" style="background-color: rgba(255, 255, 255, 0);">In your example, would Index: Foo indicate that index is exactly Foo, is Foo or some subtype, or is a concrete implementation of Foo? If there were two syntaxes, I’d hope one to be a much closer shortening of the other.</span></div></div></div></div><div class=""><br class=""></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class=""><div class=""><span class="" style="background-color: rgba(255, 255, 255, 0);"><font class="">Index: Foo</font></span></div><div class="">Index is of type Foo or a Subtype.</div></div></div></div></blockquote><div><br class=""></div>In that, the covariant case, Array&lt;Element:Number&gt; is _different_ than Array&lt;Number&gt; today.</div><div><br class=""></div><div>Today, Array&lt;Number&gt; and Array&lt;Int&gt; are different concrete types. One deals in terms of Numbers, and one in terms of Ints. They are structured in memory different, etc.</div><div><br class=""></div><div>When I say partial constraints, applied to generics in this case (reluctantly), I’m saying the following:</div><div><br class=""></div><div>Implicitly define a protocol around all concrete Array instances where Element is defined to be Number or a subtype of Number, exposing all methods, properties, etc which are safe.</div><div><br class=""></div><div>Safety rules are equivalency rules here: If a method or property returns Element, I can say that it is safe to represent the result of “var first:Element {get}” as a Number, because in the cases where it returns a subtype like Int, I can still safely upcast to Number. I have a safe and uniform interface.</div><div><br class=""></div><div>If a method takes an argument or for any property setter, I have to require Element to be invariant. Modifying the first item of an array isn’t safe, because I might try to assign an Int value when really its a UInt8 array.</div><div><br class=""></div><div>Subscripts unfortunately require both get and set, so even the getter has to be hidden currently if the type isn’t invariant. I’m not sure why the language requires this, TBH</div><div><br class=""></div><div>That we are constraining the exposure of a protocol to only expose what is available by the associated type rules we specified is why I stayed away from terse, generic type syntax to start the proposal. Eventually, consensus might be that generic type form is better, but it adds an additional complexity to the understanding of the type model, which is the important part now in discussion. You are now using an existing syntax to refer to a new thing with new properties.</div><div><br class=""></div><div>This is even more confusing if you partially constrain a generic type, because now Array&lt;Number&gt; (aka Array&lt;where Element == Number&gt; and Array&lt;where Element:Number&gt; have different properties (one is a protocol while the other is a concrete type, functionality is hidden because it is unsafe, possible boxing onto the heap and dynamic dispatch, etc)</div><div><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class=""><div class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div class="">I do have a mild personal conflict around whether exposing the ability to have partially constrained generics is a good idea, but I admit my hesitation is based on philosophies of good application and API design, and not based on language design.</div><div class=""><br class=""></div><div class="">&nbsp;implicit protocols on types seem pragmatic, because otherwise I’d have to create a protocol just for others to use me.&nbsp;</div><div class=""><br class=""></div><div class="">Allowing a protocol with associated types to be partially constrained seems pragmatic to me, since otherwise I have to use one of the workarounds above (hand-coded new protocol, generic constraints ever, and/or type-erasure struct-wrapper).</div><div class=""><br class=""></div><div class="">Expanding the usage of the implicit protocol on some generic type seems anti-pragmatic, just because it allows someone to go longer before they really evaluate whether locking consumers of their API into a single implementation is a good idea. They can always declare a protocol explicitly if they want partially constrained behavior.</div></div></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">That was also my concern since I want to keep the generic syntax consistent with protocols. So maybe we could make it the same in case of generic parameter names but without the "_" so there are no protocol like behaviors for generic types.</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Even though it would be nice to have a covariant Array&lt; _ &gt; type.</span></blockquote><div><br class=""></div>Yep :-) I can’t speak for the core team, but from my perspective whether this proposal lives or dies depends on:</div><div><br class=""></div><div>1. Implementability</div><div>2. Abiding by the Principal of Least Surprise</div><div><br class=""></div></div><div>-DW</div></body></html>