<div dir="ltr">I would like to add something to this discussion on casting generics.<div><br></div><div>I think there is a temptation to think of generic types as having a protocol-like aspect. If String conforms to Any, then a [String] ought to conform to [Any]; the current scope may think of the variable as being a [Any] even though it is really a [String] and should only accept Strings as elements. Similarly I shouldn't have to care what the element type is, if all I want from the array is its count.</div><div><br></div><div>I think generic types can be complicated, particularly if they have multiple generic components. I'm not sure that covariance and contravariance, if I'm using those terms right, should be implicit for all generic types.</div><div><br></div><div>However, I think it should be possible to explicitly make covariance or contravariance easier to achieve for certain types.</div><div><br></div><div>Practically, what I'm getting at in Swift is this: 'as' and 'as?' are keywords in Swift, but in a way they're used as operators, and it isn't possible to write custom implementations.</div><div><br></div><div>For the sake of example: I am writing a Stack<Element>. It likely has an array as a private property but it has other properties as well. I wish to cast a Stack<String> as a Stack<Any>. I cannot; they're two different types. The best I can do is write an init function for Stack which takes another Stack as an argument. The initialiser will have generic constraints because I'm using a Stack<A> as an argument to produce a Stack<B>. When this initialiser gets called, the caller will be very clear on what type they are declaring B to be, so the new Stack can establish its Element type.</div><div><br></div><div>However, the compiler would not see a problem in using a Stack<Int> as an argument to initialising a Stack<String>. I can write code in my initialiser, testing that each element of type A in the Stack<A> is of type B, and I can make my initialiser failable or throws if an A not castable to B is found, but the compiler cannot enforce the generic constraint that A : B, or B : A. (As of Swift 4, the A : B relationship could mean that A is a subclass of B, A conforms to B, or both.)</div><div><br></div><div>I would be interested in allowing the following function call as a generic constraint, so that casting generic types can be made easier:</div><div><br></div><div>func convert<A, B>(from: Stack<A>) -> Stack<B> where A : B</div><div><br></div><div>Is this a possibility?</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Aug 8, 2017 at 2:52 PM, David Sweeris via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div><div class="h5"><div><br></div><div>On Aug 8, 2017, at 06:38, Karl Wagner <<a href="mailto:razielim@gmail.com" target="_blank">razielim@gmail.com</a>> wrote:<br><br></div><blockquote type="cite"><div><br><div><blockquote type="cite"><div>On 8. Aug 2017, at 04:35, David Sweeris via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_-3152061554769996139Apple-interchange-newline"><div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite"><div><br class="m_-3152061554769996139Apple-interchange-newline">On Aug 7, 2017, at 3:00 PM, Logan Shire via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_-3152061554769996139Apple-interchange-newline"><div><div style="word-wrap:break-word">One of my longstanding frustrations with generic types and protocols has been how hard it is to work with them when their type is unspecified.<div>Often I find myself wishing that I could write a function that takes a generic type or protocol as a parameter, but doesn’t care what its generic type is.</div><div><br></div><div>For example, if I have a type:</div><div><br></div><div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"><span style="color:rgb(194,52,155)">struct</span> Foo<T> {</div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"> <span style="color:rgb(194,52,155)">let</span> name: <span style="color:rgb(0,175,202)">String</span></div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"> <span style="color:rgb(194,52,155)">let</span> value: <span style="color:rgb(147,201,106)">T</span></div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)">}</div></div><div><br></div><div>or:</div><div><br></div><div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"><span style="color:rgb(194,52,155)">protocol</span> Foo {</div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"> <span style="color:rgb(194,52,155)">associatedtype </span><span style="color:rgb(147,201,106)">T</span></div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"> <span style="color:rgb(194,52,155)">var</span> name: <span style="color:rgb(0,175,202)">String </span>{ <span style="color:rgb(194,52,155)">get </span>}</div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"> <span style="color:rgb(194,52,155)">var</span> value: <span style="color:rgb(147,201,106)">T </span>{ <span style="color:rgb(194,52,155)">get </span>}</div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)">}</div></div><div><br></div><div>And I want to write a function that only cares about Foo.name, I’d like to be able to:</div><div><br></div><div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"><span style="color:rgb(194,52,155)">func</span> sayHi(to foo: <span style="text-decoration:underline;color:rgb(0,175,202)">F</span><span style="color:rgb(0,175,202)">oo</span>) {</div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"> <span style="color:rgb(0,175,202)">print</span>(<span style="color:rgb(228,67,71)">"hi </span>\<span style="color:rgb(228,67,71)">(</span><a href="http://foo.name" target="_blank">foo.name</a><span style="color:rgb(228,67,71)">)"</span>)</div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)">}</div></div><div><br></div><div>But instead I get the error, “Reference to generic type Foo requires arguments in <…>”</div><div><br></div><div>Also, when you want to have a polymorphic array of generic types, you can’t:</div><div><br></div><div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(255,255,255);background-color:rgb(40,43,53)"><span style="color:rgb(194,52,155)">let</span> foos: [Foo] = [<span style="color:rgb(147,201,106)">Foo</span>(name: <span style="color:rgb(228,67,71)">"Int"</span>, value: <span style="color:rgb(139,132,207)">2</span>), <span style="color:rgb(147,201,106)">Foo</span>(name: <span style="color:rgb(228,67,71)">"Double"</span>, value: <span style="color:rgb(139,132,207)">2.0</span>)]</div></div><div><br></div><div>And if you remove the explicit type coercion, you just get [Any]</div><div><br></div><div><span style="font-family:Menlo;background-color:rgb(40,43,53);color:rgb(194,52,155)">let</span><span style="color:rgb(255,255,255);font-family:Menlo;background-color:rgb(40,43,53)"> foos = [</span><span style="font-family:Menlo;background-color:rgb(40,43,53);color:rgb(147,201,106)">Foo</span><span style="color:rgb(255,255,255);font-family:Menlo;background-color:rgb(40,43,53)">(name: </span><span style="font-family:Menlo;background-color:rgb(40,43,53);color:rgb(228,67,71)">"Int"</span><span style="color:rgb(255,255,255);font-family:Menlo;background-color:rgb(40,43,53)">, value: </span><span style="font-family:Menlo;background-color:rgb(40,43,53);color:rgb(139,132,207)">2</span><span style="color:rgb(255,255,255);font-family:Menlo;background-color:rgb(40,43,53)">), </span><span style="font-family:Menlo;background-color:rgb(40,43,53);color:rgb(147,201,106)">Foo</span><span style="color:rgb(255,255,255);font-family:Menlo;background-color:rgb(40,43,53)">(name: </span><span style="font-family:Menlo;background-color:rgb(40,43,53);color:rgb(228,67,71)">"Double"</span><span style="color:rgb(255,255,255);font-family:Menlo;background-color:rgb(40,43,53)">, value: </span><span style="font-family:Menlo;background-color:rgb(40,43,53);color:rgb(139,132,207)">2.0</span><span style="color:rgb(255,255,255);font-family:Menlo;background-color:rgb(40,43,53)">)]</span></div><div><br></div><div>I wish that could be inferred to be [Foo].</div></div></div></blockquote><div><br></div><div>What happens if you try to say "foos: [Foo<Any>] = ..."? </div><div><br></div></div></div></blockquote><div><br></div><div>Foo<Int> and Foo<Any> are very different. Otherwise, you could take a Foo<Int>, cast it to a Foo<Any> and set a String as its value.</div><div><br></div><div>I think what he means are partial generics, e.g: Foo<_>.</div></div></div></blockquote><br></div></div><div><span style="background-color:rgba(255,255,255,0)">Oh I know, I just couldn't remember if it'd work as long as you didn't mess with the generic bits.</span><br></div><div><span style="background-color:rgba(255,255,255,0)"><br></span></div><div><span style="background-color:rgba(255,255,255,0)">- Dave Sweeris</span></div></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>