<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&#39;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&#39;m not sure that covariance and contravariance, if I&#39;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&#39;m getting at in Swift is this: &#39;as&#39; and &#39;as?&#39; are keywords in Swift, but in a way they&#39;re used as operators, and it isn&#39;t possible to write custom implementations.</div><div><br></div><div>For the sake of example: I am writing a Stack&lt;Element&gt;. It likely has an array as a private property but it has other properties as well. I wish to cast a Stack&lt;String&gt; as a Stack&lt;Any&gt;. I cannot; they&#39;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&#39;m using a Stack&lt;A&gt; as an argument to produce a Stack&lt;B&gt;. 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&lt;Int&gt; as an argument to initialising a Stack&lt;String&gt;. I can write code in my initialiser, testing that each element of type A in the Stack&lt;A&gt; 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&lt;A, B&gt;(from: Stack&lt;A&gt;) -&gt; Stack&lt;B&gt; 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">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</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 &lt;<a href="mailto:razielim@gmail.com" target="_blank">razielim@gmail.com</a>&gt; 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 &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; 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 &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; 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&lt;T&gt; {</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)">&quot;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)">)&quot;</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 &lt;…&gt;”</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)">&quot;Int&quot;</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)">&quot;Double&quot;</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)">&quot;Int&quot;</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)">&quot;Double&quot;</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 &quot;foos: [Foo&lt;Any&gt;] = ...&quot;? </div><div><br></div></div></div></blockquote><div><br></div><div>Foo&lt;Int&gt; and Foo&lt;Any&gt; are very different. Otherwise, you could take a Foo&lt;Int&gt;, cast it to a Foo&lt;Any&gt; and set a String as its value.</div><div><br></div><div>I think what he means are partial generics, e.g: Foo&lt;_&gt;.</div></div></div></blockquote><br></div></div><div><span style="background-color:rgba(255,255,255,0)">Oh I know, I just couldn&#39;t remember if it&#39;d work as long as you didn&#39;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>