<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=""><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div class=""><div><blockquote type="cite" class=""><div class="">On 17 Oct 2016, at 20:13, Nevin Brackett-Rozinsky <<a href="mailto:nevin.brackettrozinsky@gmail.com" class="">nevin.brackettrozinsky@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">I like it!<div class=""><br class=""></div><div class="">I haven’t thought through the ramifications regarding associated types yet though.</div><div class=""><br class=""></div></div></div></blockquote><div><br class=""></div><div>Associated types are tricky. The example I gave maybe wasn’t the most practical, as to use it you’d have to write something like:<div class=""><br class=""></div><div class=""><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class="">class A<T> : MyProto where T : A.Delegate, T.ExpectedContent == String {}</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class="">which then locks you to using one static type for your delegate. Moving the associatedType up a level to MyProto means we would implement it by writing:</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class="">class A : MyProto {</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> typealias ExpectedContent = String</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> var delegate : A.Delegate</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> func notify() {</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> delegate.receive(“a string”, for: .someCase)</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> }</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class="">}</div></div><div class=""><br class=""></div><div class=""><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class="">class B : MyProto {</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> typealias ExpectedContent = Int</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> var delegate : B.Delegate</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> func notify() {</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> delegate.receive(42, for: .someCase)</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""> }</div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class="">}</div></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(69, 69, 69);" class="">Still, I think the general answer to protocols with associated types for this case is: “use a concrete type in its place”.</div></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">Is your vision that each conforming type would have to provide its own nested type as specified by the protocol?</div><div class=""><br class=""></div><div class="">Or could the protocol itself define a nested type and anything could use it?</div><div class=""><br class=""></div><div class="">protocol FloatingPoint: … {</div><div class=""> enum RoundingRule {</div><div class=""> // Do I put an implementation here?</div><div class=""> }</div><div class="">}<br class=""></div></div></div></blockquote><div><br class=""></div><div>No, types which are defined inside the protocol are implemented there. Providing your own types to satisfy a conformance is what associated types are for.</div><div><br class=""></div><div>If you wanted something like that, you could do it with a nested protocol + associated type:</div><div><br class=""></div><div>protocol FloatingPoint {</div><div><br class=""></div><div> protocol _RoundingRule { func round(_ : Super) -> Super }</div><div> associatedType RoundingRule : _RoundingRule</div><div>}</div><div><br class=""></div><div>struct Float : FloatingPoint {</div><div><br class=""></div><div> enum RoundingRule : _RoundingRule {</div><div> func round(_ val: Float) -> Float {</div><div> /* switch self, perform rounding… */ </div><div> }</div><div> }</div><div>}</div><div><br class=""></div><div>That brings up an interesting point, though - we would need a way to refer to the outer protocol (I used “Super” here).</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class=""><br class=""></div><div class="">Nevin</div><div class=""><br class=""></div><div class=""><br class=""></div></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Oct 17, 2016 at 1:59 PM, Karl via swift-evolution <span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="">I was just doing some googling, turns out there was a discussion about nesting protocols in other types that seemed to go positively a long time ago: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160425/016074.html" target="_blank" class="">https://lists.swift.org/<wbr class="">pipermail/swift-evolution/<wbr class="">Week-of-Mon-20160425/016074.<wbr class="">html</a><div class=""><br class=""></div><div class="">I would additionally like to propose that protocols be allowed to contain nested types (including other protocols). Relevant ABI issue is that the standard library contains enums for “FloatingPointRoundingRule”, “FloatingPointClassification” and “FloatingPointSign”. They would probably be better expressed as “FloatingPoint.RoundingRule”, “.Sign", etc.</div><div class=""><br class=""></div><div class="">so to summarise, newly legal would be:</div><div class=""><br class=""></div><div class="">class MyClass {</div><div class=""><br class=""></div><div class=""> protocol Delegate {</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">and also:</div><div class=""><br class=""></div><div class="">protocol MyProto {</div><div class=""><br class=""></div><div class=""> enum SomeValue {</div><div class=""> }</div><div class=""><br class=""></div><div class=""> protocol Delegate {</div><div class=""> associatedType ExpectedContent</div><div class=""><br class=""></div><div class=""><span class="m_4845095118596932916Apple-tab-span" style="white-space:pre-wrap">        </span>func receive(_: ExpectedContent, for: SomeValue)</div><div class=""><br class=""></div><div class=""> protocol SecondaryTarget {</div><div class=""> func receive(_ : ExpectedContent)</div><div class=""> }</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">When conforming to a nested protocol, you can just use the name of the protocol:</div><div class=""><br class=""></div><div class="">class Host : MyProto.Delegate {</div><div class="">}</div><div class=""><br class=""></div><div class="">Except if a protocol in the chain has associated types, then you must use a concrete, conforming type instead (as you would in the first example — MyClass.Delegate):</div><div class=""><br class=""></div><div class="">class SecondaryProcessor : Host.SecondaryTarget {</div><div class="">}</div><div class=""><br class=""></div><div class="">If we’re good with this, I’ll write up a proposal.</div><span class="HOEnZb"><font color="#888888" class=""><div class=""><div class=""><div class=""><br class=""></div><div class="">- Karl</div></div></div></font></span></div><br class="">______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></div></div></body></html>