<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 <<a href="mailto:david@alkaline-solutions.com">david@alkaline-solutions.com</a>>:<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 <<a href="mailto:m.huenenberger@me.com" class="">m.huenenberger@me.com</a>> 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 are only a demonstration of how you could use collection type</div><div class=""><br class=""></div><div class="">CollectionType<where .Generator.Element == String, .Index == Int, .SubSequence: Self></div><div class=""><br class=""></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">CollectionType<where .Generator.Element == String, .Index == Int></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<where .Generator.Element == String></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<where .Element == String></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. </div><div><br class=""></div><div>For instance, Optional<T == BooleanType> would describe a concrete Optional holding some implementation of BooleanType, while Optional<where T:BooleanType> would be a generated protocol to umbrella every Optional that matches (e.g. Optional<T == Bool>, Optional<T == ObjCBool>, …)</div><div><br class=""></div><div>Then the syntax could be identical, e.g. RawRepresentable<RawValue == Int> vs RawRepresentable<where RawValue:SignedNumberType></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<Self == Int>, 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 == ... and Self: .....) should probably only used in "protocol<>".</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> let aArray: Array<where .Element: Int> = [1,2,3] </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<where .Element == A> = [1,2,3] </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] </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> let aCovariantArray: Array<where .Element: Int> = [1,2,3] </div><div class=""> 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 </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<where .Element == A></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? </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<C: CollectionType where C.Generator.Element == A>(c: C) {}</div><div><br></div><div>takeCollection(intArray) // fails</div><div>takeCollection(aArray) // works</div><div><br></div><div><br></div><div>Or how would you interpret "<span style="background-color: rgba(255, 255, 255, 0);">CollectionType<where .Element == A>" in contrast to "CollectionType<where .Element: A>"?</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<where .Element: A></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 `A` does<span class="Apple-converted-space"> </span><b class=""><u class="">not</u></b><span class="Apple-converted-space"> </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<A>` or<span class="Apple-converted-space"> </span><span style="background-color: rgba(255, 255, 255, 0);" class="">`Array<where .Element == A>` or `[A]` or `[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<where .Element: A>` or `[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<></div><div class=""><br class=""></div><div class="">// declaring a generic type T which is used in two protocols</div><div class="">protocol<where T, Self: SequenceType<where .Element == T>, Self: Indexable<where .Index == T>></div><div class=""><br class=""></div><div class="">// although in this case it can be written as</div><div class="">SequenceType<where T, .Element == T,<span class="Apple-converted-space"> </span><span style="background-color: rgba(255, 255, 255, 0);" class="">Self: Indexable<where .Index == T>></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<> 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<T where Self: SequenceType<where .Element == T>, Self: Indexable<where .Index == T>></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<where Self: SequenceType, Self: Indexable, Self.Element == Self.Index></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 "<>" 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>=></div><div><span style="background-color: rgba(255, 255, 255, 0);">protocol<where Self: SequenceType<>, Self: Indexable<>, Self.Element == Self.Index></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>