<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 29, 2015, at 5:44 PM, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 29, 2015, at 12:06 PM, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<title class=""></title>
<div class=""><div class="">I briefly skimmed your proposal, so I apologize if you already addressed this, but it occurs to me that we could support automatic protocol forwarding today on a per-protocol basis simply by declaring a separate protocol that provides default implementations doing the forwarding. Handling of Self return types can then be done by adding a required initializer (or just not implementing that method, so the concrete type is forced to deal with it even though everything else is forwarded).<br class=""></div>
<div class=""> </div>
<div class="">For example, if I want to automatically forward SequenceType to a member, I can do something like<br class=""></div>
<div class=""> </div>
<div class=""><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">protocol</span> SequenceTypeForwarder : <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">SequenceType</span> {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">typealias</span> ForwardedSequenceType : SequenceType</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> forwardedSequence : <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ForwardedSequenceType</span> { <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">get</span> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span>SequenceTypeForwarder<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> generate() -> </span>ForwardedSequenceType<span style="font-variant-ligatures: no-common-ligatures;" class="">.</span>Generator<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.generate()</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> underestimateCount() -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span> {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.underestimateCount()</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> map<T>(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> transform: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -> T) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -> [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span>] {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.map(transform)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> filter(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> includeElement: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -> Bool) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -> [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ForwardedSequenceType</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Generator</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Element</span>] {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.filter(includeElement)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> forEach(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> body: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -> Void) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.forEach(body)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> dropFirst(n: </span>Int<span style="font-variant-ligatures: no-common-ligatures;" class="">) -> </span>ForwardedSequenceType<span style="font-variant-ligatures: no-common-ligatures;" class="">.</span>SubSequence<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.dropFirst(n)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> dropLast(n: </span>Int<span style="font-variant-ligatures: no-common-ligatures;" class="">) -> </span>ForwardedSequenceType<span style="font-variant-ligatures: no-common-ligatures;" class="">.</span>SubSequence<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.dropLast(n)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> prefix(maxLength: </span>Int<span style="font-variant-ligatures: no-common-ligatures;" class="">) -> </span>ForwardedSequenceType<span style="font-variant-ligatures: no-common-ligatures;" class="">.</span>SubSequence<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.prefix(maxLength)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> suffix(maxLength: </span>Int<span style="font-variant-ligatures: no-common-ligatures;" class="">) -> </span>ForwardedSequenceType<span style="font-variant-ligatures: no-common-ligatures;" class="">.</span>SubSequence<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.suffix(maxLength)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> split(maxSplit: Int, allowEmptySlices: Bool, <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> isSeparator: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -> Bool) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -> [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ForwardedSequenceType</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">SubSequence</span>] {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.split(maxSplit, allowEmptySlices: allowEmptySlices, isSeparator: isSeparator)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">FWIW,</div><div class=""><br class=""></div><a href="https://github.com/apple/swift/blob/master/stdlib/public/core/SequenceWrapper.swift" class="">https://github.com/apple/swift/blob/master/stdlib/public/core/SequenceWrapper.swift</a></div><div class=""><br class=""></div><div class="">Though I don’t know why we still have this; it’s not used anywhere and should probably be removed. I think it was supposed to be part of the new lazy sequence/collection subsystem but it was never incorporated.</div></div></div></blockquote><div><br class=""></div><div>Dave, thanks for pointing me to the Lazy Collections subsystem. It made for a really great case study! </div><div><br class=""></div><div>A lot of what is happening in there is not directly forwarding related. But I do think the implementation of the parts that involve forwarding is improved by using the forwarding mechanism in this proposal. It is more clear and more robust than the current implementation. </div><div><br class=""></div><div>As it turns out, _SequenceWrapperType and the extension to SequenceType in SequenceWrapper.swift actually are still in use. They contain an implementation of the forwarding mechanism Kevin Ballard suggested in this thread. _CollectionWrapperType and the extension to CollectionType are not in use. LazyCollection uses manual forwarding in the type itself which avoids some of the drawbacks of the protocol extension approach. Of course this begs the question of why two different mechanisms are in use and which is actually preferred.</div><div><br class=""></div><div>I am working on a new draft of the proposal with a greatly expanded motivation section. I don’t have that completed yet, but I have completed a first pass of the section on the lazy collection subsystem. I am including the current draft here. I hope you find it interesting. I am interested in your thoughts on it.</div><div><br class=""></div><div>Matthew</div><div><h2 id="motivation" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Motivation</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Delegation is a robust, composition oriented design technique that keeps interface and implementation inheritance separate. The primary drawback to this technique is that it requires a lot of manual boilerplate to forward implemenation to the implementing member. This proposal eliminates the need to write such boilerplate manually, thus making delegation-based designs much more convenient and attractive.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This proposal may also serve as the foundation for a future enhancement allowing a very concise “newtype” declaration. In the meantime, it facilitates similar functionality, although in a slightly more verbose manner.</p><h3 id="examples" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Examples</h3><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Several examples follow. </p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The first two show how this proposal could improve how forwarding is implemented by the lazy collection subsystem of the standard library. This makes an interesting case study as each example employs a different forwarding mechanism.</p><h4 id="lazysequence" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class=""><code style="line-height: 1;" class="">LazySequence</code></h4><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The relevant portion of the current implementation of <code style="line-height: 1;" class="">LazySequence</code> looks like this (with comments removed and formatting tweaks):</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 1422px;" class=""><code class="swift hljs" style="line-height: inherit; display: block; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// in SequenceWrapper.swift:</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">protocol</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">_SequenceWrapperType</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">typealias</span> <span class="hljs-type">Base</span> : <span class="hljs-type">SequenceType</span>
<span class="hljs-keyword" style="font-weight: bold;">typealias</span> <span class="hljs-type">Generator</span> : <span class="hljs-type">GeneratorType</span> = <span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>
<span class="hljs-keyword" style="font-weight: bold;">var</span> _base: <span class="hljs-type">Base</span> {<span class="hljs-keyword" style="font-weight: bold;">get</span>}
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">SequenceType</span>
<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">where</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Self</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">_SequenceWrapperType</span>, <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Self</span>.<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Generator</span> == <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Self</span>.<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Base</span>.<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Generator</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">generate</span><span class="hljs-params">()</span></span> -> <span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-keyword" style="font-weight: bold;">self</span>._base.generate()
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">underestimateCount</span><span class="hljs-params">()</span></span> -> <span class="hljs-type">Int</span> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base.<span class="hljs-built_in" style="color: rgb(0, 134, 179);">underestimateCount</span>()
}
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">map</span><span class="hljs-generics"><T></span><span class="hljs-params">(
@noescape transform: <span class="hljs-params">(Base.Generator.Element)</span></span></span> <span class="hljs-keyword" style="font-weight: bold;">throws</span> -> <span class="hljs-type">T</span>
) <span class="hljs-keyword" style="font-weight: bold;">rethrows</span> -> [<span class="hljs-type">T</span>] {
<span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-keyword" style="font-weight: bold;">try</span> _base.<span class="hljs-built_in" style="color: rgb(0, 134, 179);">map</span>(transform)
}
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">filter</span><span class="hljs-params">(
@noescape includeElement: <span class="hljs-params">(Base.Generator.Element)</span></span></span> <span class="hljs-keyword" style="font-weight: bold;">throws</span> -> <span class="hljs-type">Bool</span>
) <span class="hljs-keyword" style="font-weight: bold;">rethrows</span> -> [<span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>] {
<span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-keyword" style="font-weight: bold;">try</span> _base.<span class="hljs-built_in" style="color: rgb(0, 134, 179);">filter</span>(includeElement)
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_customContainsEquatableElement</span><span class="hljs-params">(
element: Base.Generator.Element
)</span></span> -> <span class="hljs-type">Bool</span>? {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._customContainsEquatableElement(element)
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_preprocessingPass</span><span class="hljs-generics"><R></span><span class="hljs-params">(@noescape preprocess: <span class="hljs-params">(<span class="hljs-keyword" style="font-weight: bold;">Self</span>)</span></span></span> -> <span class="hljs-type">R</span>) -> <span class="hljs-type">R</span>? {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._preprocessingPass { <span class="hljs-number" style="color: rgb(0, 153, 153);">_</span> <span class="hljs-keyword" style="font-weight: bold;">in</span> preprocess(<span class="hljs-keyword" style="font-weight: bold;">self</span>) }
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_copyToNativeArrayBuffer</span><span class="hljs-params">()</span></span>
-> _ContiguousArrayBuffer<<span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._copyToNativeArrayBuffer()
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_initializeTo</span><span class="hljs-params">(ptr: UnsafeMutablePointer<Base.Generator.Element>)</span></span>
-> <span class="hljs-type">UnsafeMutablePointer</span><<span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._initializeTo(ptr)
}
}
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// in LazySequence.swift:</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">struct</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazySequence</span><<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Base</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">SequenceType</span>>
: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazySequenceType</span>, <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">_SequenceWrapperType</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">init</span>(<span class="hljs-number" style="color: rgb(0, 153, 153);">_</span> base: <span class="hljs-type">Base</span>) {
<span class="hljs-keyword" style="font-weight: bold;">self</span>._base = base
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> _base: <span class="hljs-type">Base</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> elements: <span class="hljs-type">Base</span> { <span class="hljs-keyword" style="font-weight: bold;">return</span> _base }
}
</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class=""><code style="line-height: 1;" class="">LazySequence</code> is using the approach to forwarding mentioned by Kevin Ballard <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151228/004755.html" style="color: rgb(13, 110, 161); text-decoration: none; transition: color 0.2s ease-in-out; -webkit-transition: color 0.2s ease-in-out;" class="">on the mailing list</a>in response to this proposal. This approach has several deficiencies that directly impact <code style="line-height: 1;" class="">LazySequence</code>:</p><ol style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;" class=""><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class=""><code style="line-height: 1;" class="">LazySequence</code> must publicly expose implementation details. Both its <code style="line-height: 1;" class="">_base</code> property as well as its conformance to <code style="line-height: 1;" class="">_SequenceWrapperType</code>.</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">The forwarding members must be manually implemented. They are trivial, but mistakes are still possible. In this case, <code style="line-height: 1;" class="">@warn_unused_result</code> is missing in some places where it should probably be specified (and would be synthesized using the approach in this proposal due to its presence in the protocol member declarations).</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">It is not immediately apparent that <code style="line-height: 1;" class="">_SequenceWrapperType</code> and the corresponding extension <strong style="line-height: 1;" class="">only</strong> provide forwarding members. Even if the name clearly indicates that it is possible that the code does something different. It is possible for somebody to come along after the initial implementation and add a new method that does something other than simple forwarding.</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">Because the forwarding is implemented via a protocol extension as default methods it can be overriden by an extension on <code style="line-height: 1;" class="">LazySequence</code>.</div></li></ol><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Here is an alternative implemented using the current proposal:</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 1212px;" class=""><code class="swift hljs" style="line-height: inherit; display: block; padding: 0.5em; color: rgb(51, 51, 51); height: auto;">
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// _LazySequenceForwarding redeclares the subset of the members of SequenceType we wish to forward.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// The protocol is an implementation detail and is marked private.</span>
<span class="hljs-keyword" style="font-weight: bold;">private</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">protocol</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">_LazySequenceForwarding</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">typealias</span> <span class="hljs-type">Generator</span> : <span class="hljs-type">GeneratorType</span>
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">generate</span><span class="hljs-params">()</span></span> -> <span class="hljs-type">Generator</span>
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">underestimateCount</span><span class="hljs-params">()</span></span> -> <span class="hljs-type">Int</span>
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">map</span><span class="hljs-generics"><T></span><span class="hljs-params">(
@noescape transform: <span class="hljs-params">(Generator.Element)</span></span></span> <span class="hljs-keyword" style="font-weight: bold;">throws</span> -> <span class="hljs-type">T</span>
) <span class="hljs-keyword" style="font-weight: bold;">rethrows</span> -> [<span class="hljs-type">T</span>]
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">filter</span><span class="hljs-params">(
@noescape includeElement: <span class="hljs-params">(Generator.Element)</span></span></span> <span class="hljs-keyword" style="font-weight: bold;">throws</span> -> <span class="hljs-type">Bool</span>
) <span class="hljs-keyword" style="font-weight: bold;">rethrows</span> -> [<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>]
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_customContainsEquatableElement</span><span class="hljs-params">(
element: Generator.Element
)</span></span> -> <span class="hljs-type">Bool</span>?
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_copyToNativeArrayBuffer</span><span class="hljs-params">()</span></span> -> _ContiguousArrayBuffer<<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>>
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_initializeTo</span><span class="hljs-params">(ptr: UnsafeMutablePointer<Generator.Element>)</span></span>
-> <span class="hljs-type">UnsafeMutablePointer</span><<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>>
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">struct</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazySequence</span><<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Base</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">SequenceType</span>> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazySequenceType</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">init</span>(<span class="hljs-number" style="color: rgb(0, 153, 153);">_</span> base: <span class="hljs-type">Base</span>) {
<span class="hljs-keyword" style="font-weight: bold;">self</span>._base = base
}
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// <span class="hljs-doctag">NOTE:</span> _base is now internal</span>
<span class="hljs-keyword" style="font-weight: bold;">internal</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> _base: <span class="hljs-type">Base</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> elements: <span class="hljs-type">Base</span> { <span class="hljs-keyword" style="font-weight: bold;">return</span> _base }
<span class="hljs-keyword" style="font-weight: bold;">public</span> forward _LazySequenceForwarding to _base
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// The current proposal does not currently support forwarding </span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// of members with nontrivial Self requirements.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// Because of this _preprocessingPass is forwarded manually.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// A future enhancement may be able to support automatic</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// forwarding of protocols with some or all kinds of </span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// nontrivial Self requirements.</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_preprocessingPass</span><span class="hljs-generics"><R></span><span class="hljs-params">(@noescape preprocess: <span class="hljs-params">(<span class="hljs-keyword" style="font-weight: bold;">Self</span>)</span></span></span> -> <span class="hljs-type">R</span>) -> <span class="hljs-type">R</span>? {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._preprocessingPass { <span class="hljs-number" style="color: rgb(0, 153, 153);">_</span> <span class="hljs-keyword" style="font-weight: bold;">in</span> preprocess(<span class="hljs-keyword" style="font-weight: bold;">self</span>) }
}
}</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This example takes advantage of a very important aspect of the design of this proposal. Neither <code style="line-height: 1;" class="">Base</code> nor <code style="line-height: 1;" class="">LazySequence</code> are required to conform to <code style="line-height: 1;" class="">_LazySequenceForwarding</code>. The only requirement is that <code style="line-height: 1;" class="">Base</code> contains the members specified in <code style="line-height: 1;" class="">_LazySequenceForwarding</code> as they will be used in the synthesized forwarding implementations. </p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The relaxed requirement is crucial to the application of the protocol forwarding feature in this implementation. We <strong style="line-height: 1;" class="">cannot</strong> conform <code style="line-height: 1;" class="">Base</code> to <code style="line-height: 1;" class="">_LazySequenceForwarding</code>. If it were possible to conform one protocol to another we could conform <code style="line-height: 1;" class="">SequenceType</code> to <code style="line-height: 1;" class="">_LazySequenceForwarding</code>, however it is doubtful that we would want that conformance. Despite this, it is clear to the compiler that <code style="line-height: 1;" class="">Base</code> does contain the necessary members for forwarding as it conforms to <code style="line-height: 1;" class="">LazySequence</code> which also declares all of the necessary members. </p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This implementation is more robust and more clear:</p><ol style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;" class=""><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">We no longer leak any implementation details.</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">There is no chance of making a mistake in the implementation of the forwarded members. It is possible that a mistake could be made in the member declarations in <code style="line-height: 1;" class="">_LazySequenceForwarding</code>. However, if a mistake is made there a compiler error will result.</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">The set of forwarded methods is immediately clear, with the exception of <code style="line-height: 1;" class="">_preprocessingPass</code> because of its nontrivial <code style="line-height: 1;" class="">Self</code> requirement. Removing the limitation on nontrivial <code style="line-height: 1;" class="">Self</code> requirements is a highly desired improvement to this proposal or future enhancement to this feature.</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">The forwarded members cannot be overriden in an extension on <code style="line-height: 1;" class="">LazySequence</code>. If somebody attempts to do so it will result in an ambiguous use error at call sites.</div></li></ol><h4 id="lazycollection" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class=""><code style="line-height: 1;" class="">LazyCollection</code></h4><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The relevant portion of the current implementation of <code style="line-height: 1;" class="">LazyCollection</code> looks like this (with comments removed and formatting tweaks):</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 1632px;" class=""><code class="swift hljs" style="line-height: inherit; display: block; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// in LazyCollection.swift:</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">struct</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazyCollection</span><<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Base</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">CollectionType</span>>
: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazyCollectionType</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">typealias</span> <span class="hljs-type">Elements</span> = <span class="hljs-type">Base</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> elements: <span class="hljs-type">Elements</span> { <span class="hljs-keyword" style="font-weight: bold;">return</span> _base }
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">typealias</span> <span class="hljs-type">Index</span> = <span class="hljs-type">Base</span>.<span class="hljs-type">Index</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">init</span>(<span class="hljs-number" style="color: rgb(0, 153, 153);">_</span> base: <span class="hljs-type">Base</span>) {
<span class="hljs-keyword" style="font-weight: bold;">self</span>._base = base
}
<span class="hljs-keyword" style="font-weight: bold;">internal</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> _base: <span class="hljs-type">Base</span>
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazyCollection</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">SequenceType</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">generate</span><span class="hljs-params">()</span></span> -> <span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span> { <span class="hljs-keyword" style="font-weight: bold;">return</span> _base.generate() }
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">underestimateCount</span><span class="hljs-params">()</span></span> -> <span class="hljs-type">Int</span> { <span class="hljs-keyword" style="font-weight: bold;">return</span> _base.<span class="hljs-built_in" style="color: rgb(0, 134, 179);">underestimateCount</span>() }
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_copyToNativeArrayBuffer</span><span class="hljs-params">()</span></span>
-> _ContiguousArrayBuffer<<span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._copyToNativeArrayBuffer()
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_initializeTo</span><span class="hljs-params">(
ptr: UnsafeMutablePointer<Base.Generator.Element>
)</span></span> -> <span class="hljs-type">UnsafeMutablePointer</span><<span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._initializeTo(ptr)
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_customContainsEquatableElement</span><span class="hljs-params">(
element: Base.Generator.Element
)</span></span> -> <span class="hljs-type">Bool</span>? {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._customContainsEquatableElement(element)
}
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazyCollection</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">CollectionType</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> startIndex: <span class="hljs-type">Base</span>.<span class="hljs-type">Index</span> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base.startIndex
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> endIndex: <span class="hljs-type">Base</span>.<span class="hljs-type">Index</span> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base.endIndex
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">subscript</span>(position: <span class="hljs-type">Base</span>.<span class="hljs-type">Index</span>) -> <span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base[position]
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">subscript</span>(bounds: <span class="hljs-type">Range</span><<span class="hljs-type">Index</span>>) -> <span class="hljs-type">LazyCollection</span><<span class="hljs-type">Slice</span><<span class="hljs-type">Base</span>>> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-type">Slice</span>(base: _base, bounds: bounds).<span class="hljs-built_in" style="color: rgb(0, 134, 179);">lazy</span>
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> isEmpty: <span class="hljs-type">Bool</span> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base.isEmpty
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> <span class="hljs-built_in" style="color: rgb(0, 134, 179);">count</span>: <span class="hljs-type">Index</span>.<span class="hljs-type">Distance</span> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base.<span class="hljs-built_in" style="color: rgb(0, 134, 179);">count</span>
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_customIndexOfEquatableElement</span><span class="hljs-params">(
element: Base.Generator.Element
)</span></span> -> <span class="hljs-type">Index</span>?? {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base._customIndexOfEquatableElement(element)
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> first: <span class="hljs-type">Base</span>.<span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>? {
<span class="hljs-keyword" style="font-weight: bold;">return</span> _base.first
}
}</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class=""><code style="line-height: 1;" class="">LazyCollection</code> is using direct manual implementations of forwarding methods. It corresponds exactly to implementations that would be synthesized by the compiler under this proposal. This approach avoids some of the problems with the first approach:</p><ol style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;" class=""><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">It does not leak implementation details. This is good!</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">The forwarded members cannot be overriden.</div></li></ol><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Unfortunately it still has some drawbacks:</p><ol style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;" class=""><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">It is still possible to make mistakes in the manual forwarding implementations.</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">The set of forwarded methods is even less clear than under the first approach as they are now potentially interspersed with custom, nontrivial member implementations, such as <code style="line-height: 1;" class="">subscript(bounds: Range<Index>) -> LazyCollection<Slice<Base>></code> in this example.</div></li><li style="font-size: 17px;" class=""><div style="word-wrap: break-word; margin: 0px; line-height: 1.3125em;" class="">This approach requires reimplementing the forwarded members in every type which forwards them and is therefore less scalable than the first approach and this proposal. This may not matter for <code style="line-height: 1;" class="">LazyCollection</code> but it may well matter in other cases.</div></li></ol><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">One intersting difference to note between <code style="line-height: 1;" class="">LazySequence</code> and <code style="line-height: 1;" class="">LazyCollection</code> is that <code style="line-height: 1;" class="">LazySequence</code> forwards three members which <code style="line-height: 1;" class="">LazyCollection</code> does not: <code style="line-height: 1;" class="">map</code>, <code style="line-height: 1;" class="">filter</code>, and <code style="line-height: 1;" class="">_preprocessingPass</code>. It is unclear whether this difference is intentional or not. </p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This difference is particularly interesting in the case of <code style="line-height: 1;" class="">_preprocessingPass</code>. <code style="line-height: 1;" class="">LazyCollection</code>appears to be using the default implementation for <code style="line-height: 1;" class="">CollectionType</code> in Collection.swift, which results in <code style="line-height: 1;" class="">_base._preprocessingPass</code> not getting called. It is not apparent why this behavior would be correct for <code style="line-height: 1;" class="">LazyCollection</code> and not for <code style="line-height: 1;" class="">LazySequence</code>.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">I wonder if the difference in forwarded members is partly due to the fact that the set of forwarded members is not as clear as it could be. </p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Here is an alternate approach implemented using the current proposal. It assumes that the same <code style="line-height: 1;" class="">SequenceType</code> members that are forwarded by <code style="line-height: 1;" class="">LazySequence</code> should also be forwarded by <code style="line-height: 1;" class="">LazyCollection</code>, allowing us to reuse the <code style="line-height: 1;" class="">_LazySequenceForwarding</code> protocol declared in the first example.</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 960px;" class=""><code class="swift hljs" style="line-height: inherit; display: block; padding: 0.5em; color: rgb(51, 51, 51); height: auto;">
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// _LazyCollectionForwarding redeclares the subset of the members of Indexable and CollectionType we wish to forward.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// The protocol is an implementation detail and is marked private.</span>
<span class="hljs-keyword" style="font-weight: bold;">private</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">protocol</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">_LazyCollectionForwarding</span>: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">_LazySequenceForwarding</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">typealias</span> <span class="hljs-type">Index</span> : <span class="hljs-type">ForwardIndexType</span>
<span class="hljs-keyword" style="font-weight: bold;">var</span> startIndex: <span class="hljs-type">Index</span> {<span class="hljs-keyword" style="font-weight: bold;">get</span>}
<span class="hljs-keyword" style="font-weight: bold;">var</span> endIndex: <span class="hljs-type">Index</span> {<span class="hljs-keyword" style="font-weight: bold;">get</span>}
<span class="hljs-keyword" style="font-weight: bold;">typealias</span> _Element
<span class="hljs-keyword" style="font-weight: bold;">subscript</span>(position: <span class="hljs-type">Index</span>) -> _Element {<span class="hljs-keyword" style="font-weight: bold;">get</span>}
<span class="hljs-keyword" style="font-weight: bold;">var</span> isEmpty: <span class="hljs-type">Bool</span> { <span class="hljs-keyword" style="font-weight: bold;">get</span> }
<span class="hljs-keyword" style="font-weight: bold;">var</span> <span class="hljs-built_in" style="color: rgb(0, 134, 179);">count</span>: <span class="hljs-type">Index</span>.<span class="hljs-type">Distance</span> { <span class="hljs-keyword" style="font-weight: bold;">get</span> }
<span class="hljs-keyword" style="font-weight: bold;">var</span> first: <span class="hljs-type">Generator</span>.<span class="hljs-type">Element</span>? { <span class="hljs-keyword" style="font-weight: bold;">get</span> }
<span class="hljs-preprocessor" style="color: rgb(153, 153, 153); font-weight: bold;">@warn_unused_result</span>
<span class="hljs-func"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">_customIndexOfEquatableElement</span><span class="hljs-params">(element: Generator.Element)</span></span> -> <span class="hljs-type">Index</span>??
}
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">struct</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazyCollection</span><<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Base</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">CollectionType</span>>
: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazyCollectionType</span> </span>{
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">typealias</span> <span class="hljs-type">Elements</span> = <span class="hljs-type">Base</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> elements: <span class="hljs-type">Elements</span> { <span class="hljs-keyword" style="font-weight: bold;">return</span> _base }
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">init</span>(<span class="hljs-number" style="color: rgb(0, 153, 153);">_</span> base: <span class="hljs-type">Base</span>) {
<span class="hljs-keyword" style="font-weight: bold;">self</span>._base = base
}
<span class="hljs-keyword" style="font-weight: bold;">internal</span> <span class="hljs-keyword" style="font-weight: bold;">var</span> _base: <span class="hljs-type">Base</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> forward _LazyCollectionForwarding to _base
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// It may be the case that LazyCollection should forward _preprocessingPass </span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// in the same fashion that LazySequence uses, which cannot yet be automated</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// under the current proposal.</span>
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">LazyCollection</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">CollectionType</span> </span>{
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This implementation is nontrivial and thus not forwarded</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">subscript</span>(bounds: <span class="hljs-type">Range</span><<span class="hljs-type">Index</span>>) -> <span class="hljs-type">LazyCollection</span><<span class="hljs-type">Slice</span><<span class="hljs-type">Base</span>>> {
<span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-type">Slice</span>(base: _base, bounds: bounds).<span class="hljs-built_in" style="color: rgb(0, 134, 179);">lazy</span>
}
}</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This approach to forwarding does not exhibit any of the issues with the manual approach and only takes about half as much code now that we are able to reuse the previous declaration of <code style="line-height: 1;" class="">_LazySequenceForwarding</code>.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">NOTE: <code style="line-height: 1;" class="">LazyMapCollection</code> in Map.swift uses the same manual forwarding approach as <code style="line-height: 1;" class="">LazyCollection</code> to forward a handful of members and would therefore also be a candidate for adopting the new forwarding mechanism as well.</p></div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="">
<div class="">With this protocol declared, I can then say something like<br class=""></div>
<div class=""> </div>
<div class=""><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span> Foo {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> ary: [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>]</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span>Foo<span style="font-variant-ligatures: no-common-ligatures;" class=""> : </span>SequenceTypeForwarder<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> forwardedSequence: [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>] { <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> ary }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div>
<div class=""> </div>
<div class="">and my struct Foo now automatically implements SequenceType by forwarding to its variable `ary`.<br class=""></div>
<div class=""> </div>
<div class="">The downside to this is it needs to be manually declared for each protocol. But I wager that most protocols actually aren't really amenable to forwarding anyway.<br class=""></div>
<div class=""> </div>
<div class="">-Kevin Ballard</div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=JfMPa-2F7wwZPzsZ3QKA8NjtONIYX4SjbWuUxtpfsTY2hhI3v8QnpPSi-2FxsYaa7tVKf7yF1VKLri6MOMq73YX2nNU8usSuPRjudk0FltucGJaIeshbnFbEPlImYqIP3jLlk6GyQopq6-2BndReThVjbAXSzzS8nYW8v8Uk-2FHC8Q-2Ff0meMn4gn9UkDgn5irGM37ISQIyUI1o-2F15-2BimCnJmHFpD1fKQ3NbFA3OWqUMXMO9HZ8-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<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" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class="">
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=eLFMrKDT8iBxZ-2Fbnk-2BZqvSchNN-2FvYXdceA0T7VxwkAfLSuSkbljnds-2FIc2KZ6UwJsdAJ3WUePZYhz0tVIpmWCrt96A4Kpterj-2BenFIf5ZIe4TrsZdfvd9c4svid0jMbD41vF7cs-2FkLPpK1WXJJXFicKJSHI6lcc8ySpDHfj9ErcXJXa6mO19-2F7tQPtgCTKuiu-2FiHWhglAfBIQ5ZesvhwZNKpbMDVhNHf5FbQuvk8ORc-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>