<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><span></span></div><div><div></div><div><br></div><div><br>Am 26.01.2016 um 00:27 schrieb David Waite &lt;<a href="mailto:david@alkaline-solutions.com">david@alkaline-solutions.com</a>&gt;:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 25, 2016, at 2:52 PM, Maximilian Hünenberger &lt;<a href="mailto:m.huenenberger@me.com" class="">m.huenenberger@me.com</a>&gt; wrote:</div><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=""><div class=""><div class=""><div class=""><div class=""><div class=""><br class=""></div><div class="">I don't think that this would be confusing since `where` indicates that the type is used in a more generic way.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">You've convinced me. I wanted to keep the generic syntax simple but having thought over it your proposal it much better in handling more complex cases without introducing additional syntax.</div><div class="">Also considering Swifts type inference where types with long names are easier to use.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">A "small" overview of several examples:</div><div class=""><br class=""></div><div class="">Using the former example of CollectionType which is used as a more concrete type (using a "leading dot" which is the same as `Self.`).</div><div class=""><br class=""></div><div class="">// These examples&nbsp;are only a demonstration of how you could&nbsp;use collection type</div><div class=""><br class=""></div><div class="">CollectionType&lt;where .Generator.Element == String, .Index == Int, .SubSequence: Self&gt;</div><div class=""><br class=""></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">CollectionType&lt;where .Generator.Element == String, .Index == Int&gt;</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="">CollectionType&lt;where .Generator.Element == String&gt;</span></div><div class=""><br class=""></div><div class="">// if having `Element` as associated type</div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">CollectionType&lt;where .Element == String&gt;</span></div></div></div></div></div></div></div></blockquote><div><br class=""></div><div>One possible/fun option for syntax would be *if* Generics changed to have the types labelled. In that case, “where” becomes a keyword to distinguish a partial vs full constraint.&nbsp;</div><div><br class=""></div><div>For instance, Optional&lt;T == BooleanType&gt; would describe a concrete Optional holding some implementation of BooleanType, while Optional&lt;where T:BooleanType&gt; would be a generated protocol to umbrella every Optional that matches (e.g. Optional&lt;T == Bool&gt;, Optional&lt;T == ObjCBool&gt;, …)</div><div><br class=""></div><div>Then the syntax could be identical, e.g.&nbsp;RawRepresentable&lt;RawValue == Int&gt; vs RawRepresentable&lt;where RawValue:SignedNumberType&gt;</div><div><br class=""></div></div></div></blockquote><div><br></div><div>That's a great idea. I wonder if the leading dot should be omitted since there is no "where" clause. In ambiguous situations you could then add "Self." or only the leading dot.</div><div>There could also be an exhaustiveness check if there is no "where", while forcing to write "where" if the protocol is partially applied.</div><br><blockquote type="cite"><div><div><div>For protocols with self requirements you would likely force “where” syntax. I can say Equatable&lt;Self == Int&gt;, but the protocol can *only* be implemented by one type in the system, Int. I can’t think of a reason to support this.</div></div></div></blockquote><div><br></div><div>Direct self constraints (Self == ... &nbsp; and &nbsp; Self: .....) should probably only used in "protocol&lt;&gt;".</div><br><blockquote type="cite"><div><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=""><div class=""><div class=""><div class=""><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">// covariance and invariance</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="">protocol A {}</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">extension Int: A {}</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="">let intArray: [Int] = [1, 2, 3]</div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">let aArray: [A] = [1, 2, 3]</span></div></div></div></div></div></div></blockquote><div><br class=""></div>probably still:</div><div>&nbsp; let aArray: Array&lt;where .Element: Int&gt; = [1,2,3]&nbsp;</div><div><br class=""></div><div>if you really want covariance. The limitations (detailed in the other email reply) are such that it is better to have clear syntax so people recognize there may be ramifications.</div></div></blockquote><div><br></div><div>I don't want implicit/inferred covariant types.</div><div>In this case invariant array:</div><div><br></div><div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">let aArray: Array&lt;where .Element == A&gt; = [1,2,3]&nbsp;</span></font></div></div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">// which is equivalent to</span></font></div><div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">let aArray: [A] = [1,2,3]&nbsp;</span></font></div></div><br><blockquote type="cite"><div><div><br class=""></div><div>I could however see a way of doing</div><div><div>&nbsp; let aCovariantArray: Array&lt;where .Element: Int&gt; = [1,2,3]&nbsp;</div><div class="">&nbsp; let aArray = aCovaraintArray as [A]</div><div class=""><br class=""></div><div class="">being allowed, just as "intArray as [A]" works today due to internal behavior.</div><div class=""><br class=""></div></div><div>I detailed the ramifications of “is a concrete array of some specific implementation of A” behavior in the other half of my response - you are basically blocking a good deal of mutation behavior due to type safety. The restrictions are such that&nbsp;</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=""><div class=""><div class=""><div class=""><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">var col1: CollectionType&lt;where .Element == A&gt;</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">col1 = intArray // doesn't work since Int != A</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">col1 = aArray // obviously works</span></div></div></div></div></div></div></blockquote><div><br class=""></div><div>The last line actually will fail as well if aArray is covariant on Element being A.</div><div><br class=""></div></div></div></blockquote><div><br></div><div>"aArray" is not covariant to "intArray" although each element is covariant to any type which conforms to "A".</div><br><blockquote type="cite"><div><div><div>CollectionType “col1” is being constrained by Elements which *are* A, while aArray is a Collection type which is constrained by Elements being A *or* any subtype. if “intArray” doesn’t work directly and isn’t safe to work directly, why would discarding some of its type information by assigning to aArray make a difference?&nbsp;</div></div></div></blockquote><div><br></div><div>I was inspired from the current generic system of functions:</div><div><br></div><div>func takeCollection&lt;C: CollectionType where C.Generator.Element == A&gt;(c: C) {}</div><div><br></div><div>takeCollection(intArray) // fails</div><div>takeCollection(aArray) &nbsp;// works</div><div><br></div><div><br></div><div>Or how would you interpret "<span style="background-color: rgba(255, 255, 255, 0);">CollectionType&lt;where .Element == A&gt;" in contrast to "CollectionType&lt;where .Element: A&gt;"?</span></div><div><br></div><blockquote type="cite"><div><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=""><div class=""><div class=""><div class=""><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">var col2: CollectionType&lt;where .Element: A&gt;</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">// both work since `Int` and `A` conform to `A` (currently in Swift 2.2&nbsp;`A` does<span class="Apple-converted-space">&nbsp;</span><b class=""><u class="">not</u></b><span class="Apple-converted-space">&nbsp;</span>conform to `A`, I don't know if this is a feature)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">col2 = intArray</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">col2 = aArray</span></div></div></div></div></div></div></blockquote><br class=""></div><div>Yep!</div><div><br class=""><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=""><div class=""><div class=""><div class=""><div class=""><div class="">// with a concrete type using the example above:</div><div class=""><br class=""></div><div class="">// replace type of `col1` with (all replacements are equivalent)</div><div class="">`Array&lt;A&gt;` or<span class="Apple-converted-space">&nbsp;</span><span style="background-color: rgba(255, 255, 255, 0);" class="">`Array&lt;where .Element == A&gt;` or&nbsp;`[A]` or&nbsp;`[where .Element == A]`</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">// replace type of `col2` with (all replacements are equivalent)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">`Array&lt;where .Element: A&gt;` or&nbsp;`[where .Element: A]`</span></div></div></div></div></div></div></div></blockquote><div><br class=""></div>I think yes, although col1 = aArray will still fail :D</div></div></blockquote><div><br></div><div>Why should this fail? Both have the exact same type "[A]".</div><br><blockquote type="cite"><div><div><br class=""><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=""><div class=""><div class=""><div class=""><div class=""><div class="">// to be discussed: using many protocols together with protocol&lt;&gt;</div><div class=""><br class=""></div><div class="">// declaring a generic type T which is used in two protocols</div><div class="">protocol&lt;where T, Self: SequenceType&lt;where .Element == T&gt;, Self: Indexable&lt;where .Index == T&gt;&gt;</div><div class=""><br class=""></div><div class="">// although in this case it can be written as</div><div class="">SequenceType&lt;where T, .Element == T,<span class="Apple-converted-space">&nbsp;</span><span style="background-color: rgba(255, 255, 255, 0);" class="">Self: Indexable&lt;where .Index == T&gt;&gt;</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="">Even though the latter one is shorter I'm skeptical about using `Self:` in protocol where clauses since at a first glance it implies that the type is only a `SequenceType`.</div></div></div></div></div></div></blockquote><div><br class=""></div><div>protocol&lt;&gt; is there for describing multiple protocols, so I’d go for the 1st.</div></div></div></blockquote><div><br></div><div>+1 For using the first</div><div><br></div><div>Suggestion:</div><div>separate declaration of T to make it consistent with current generic syntax</div><div><br></div><div><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">protocol&lt;T where Self: SequenceType&lt;where .Element == T&gt;, Self: Indexable&lt;where .Index == T&gt;&gt;</span></font></div><div class=""><br></div><div class="">This example could also be rewritten to:</div><div class=""><span style="background-color: rgba(255, 255, 255, 0);">protocol&lt;where Self: SequenceType, Self: Indexable, Self.Element == Self.Index&gt;</span></div></div></div></div></div></div></div><div><br></div><div><br></div><div>Another suggestion:</div><div>For completely unconstrained protocols with associated types "&lt;&gt;" could be added at the end of the type to indicate that they have associated types in comparison to protocols which don't have them.</div><div>=&gt;</div><div><span style="background-color: rgba(255, 255, 255, 0);">protocol&lt;where Self: SequenceType&lt;&gt;, Self: Indexable&lt;&gt;, Self.Element == Self.Index&gt;</span></div><div><br></div><div><br></div><div>- Maximilian</div><br><blockquote type="cite"><div><div><div><br class=""></div><div>-DW</div></div><br class=""></div></blockquote></div></body></html>