<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 2, 2017 at 8:50 AM, David Hart 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>I&#39;m not giving my opinion, but quoting Ben Cohen&#39;s great list of questions to ask ourselves before adding something to the Standard Library:</div><div id="m_-6256791494750821676AppleMailSignature"><br></div><div id="m_-6256791494750821676AppleMailSignature"><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px"><span style="background-color:rgba(255,255,255,0)">All methods added to the standard library increase complexity, so need a strong justification to reduce the risk of API sprawl. When requesting additions/modifications, please keep the following questions in mind:</span></p><ol style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px"><li style="box-sizing:border-box"><span style="background-color:rgba(255,255,255,0)">Is the suggested addition a common operation that many would find useful? Can it be flexible enough to cover different needs?</span></li><li style="box-sizing:border-box;margin-top:0.25em"><span style="background-color:rgba(255,255,255,0)">Will it encourage good practice? Might it be misused or encourage anti-patterns?</span></li><li style="box-sizing:border-box;margin-top:0.25em"><span style="background-color:rgba(255,255,255,0)">Can the operation be composed simply from existing std lib features? Is that composition intuitive/readable? </span></li><li style="box-sizing:border-box;margin-top:0.25em"><span style="background-color:rgba(255,255,255,0)">Is writing the equivalent by hand hard to get right? Are there common correctness traps that this addition would help avoid?</span></li><li style="box-sizing:border-box;margin-top:0.25em"><span style="background-color:rgba(255,255,255,0)">Is writing the equivalent by hand hard to make efficient? Are there common performance traps that this addition would help avoid?</span></li></ol></div></div></blockquote><div>I would advocate that point 5 can indeed be a bit hard (however I am not sure that would justify the addition to the standard library). I often use the functions &quot;repmat&quot; and &quot;ndgrid&quot; in MATLAB to prepare collections of indexes to consider batch computations / combinatory problems. Due to the limitation of the MATLAB language only indexes or parameters values are usually contained in the repeated collections/matrices. As a consequence, the object obtained through the repeatition usually remain manageable in terms of memory.<br><br>If, however, people would like to do such things directly on some collections of objects with resaonnable size, we might end up copying a lot of data for nothing. It might also force programmers to modify their classes / data structure to avoid this problem. As long as the &quot;repeated&quot; data/collection is only used only for read operations (which I imagine to be one of the main use cases with the for-in loops), copies could be prevented. <br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div id="m_-6256791494750821676AppleMailSignature"><ol style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px"><li style="box-sizing:border-box;margin-top:0.25em"><span style="background-color:rgba(255,255,255,0)">Might a native implementation be able to execute more efficiently, by accessing internals, than the equivalent implementation using public APIs?</span></li></ol></div><div><div class="h5"><div><br>On 2 May 2017, at 07:02, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr">On Mon, May 1, 2017 at 9:34 PM, Karl Wagner 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><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Currently, we have the Repeated&lt;T&gt; type, which presents a single element as though it were a Collection. <div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="Courier">&gt; for i in repeatElement(1, count: 3) { print(i) }</font></div><div><font face="Courier">1</font></div><div><font face="Courier">1</font></div><div><font face="Courier">1</font></div><div><font face="Courier"><br></font></div><div><font face="Courier">&gt; for i in repeatElement([1, 2, 3], count: 3) { print(i) }</font></div><div><font face="Courier">[1, 2, 3]</font></div><div><font face="Courier">[1, 2, 3]</font></div><div><font face="Courier">[1, 2, 3]</font></div></blockquote><div><br></div><div>However, we lack the ability for Collections to repeat their contents in a single list; basically, some kind of “flatMap” to repeatElement’s “map”. So I’d like to pitch a new API for repeated values. </div><div><br></div><div>- We would add a RepeatCollection&lt;C: Collection&gt; type, which loops over its base Collection a certain number of times (or until a maximum ‘count’). </div><div>  Implementation might look something like this (<a href="https://gist.github.com/karwa/5228974a0b4dfd000a916f0aac2721c6" target="_blank">https://gist.github.com/karwa<wbr>/5228974a0b4dfd000a916f0aac272<wbr>1c6</a>), except that we’d add some optimised map(), filter() and contains() functions which apply the algorithm once to the base and multiply the result.</div><div><br></div><div>- We would add 3 new functions to all Collections:</div><div><br></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><font face="Courier">/// Repeats the collection <i>itself</i> N times.</font></div></div><div><div><font face="Courier">///</font></div></div><div><div><font face="Courier">func repeated(_ times: Int) -&gt; RepeatCollection&lt;CollectionOfO<wbr>ne&lt;Self&gt;&gt;</font></div></div><div><div><font face="Courier"><br></font></div></div><div><div><font face="Courier">/// Repeats the collection’s <i>contents</i> N times.</font></div></div><div><div><font face="Courier">///</font></div></div><div><div><font face="Courier">func repeatElements(_ times: Int) -&gt; RepeatCollection&lt;Self&gt;</font></div></div><div><div><font face="Courier"><br></font></div></div><div><div><font face="Courier">/// Loops the collection’s contents to present a Collection of length N.</font></div></div><div><div><font face="Courier">///</font></div></div><div><div><font face="Courier">func repeatElements(count: Int) -&gt; RepeatCollection&lt;Self&gt;</font></div></div></blockquote><div><div><br></div><div>- We would replace the existing Repeated&lt;T&gt; type with a typealias to RepeatCollection&lt;CollectionOfO<wbr>ne&lt;T&gt;&gt;</div><div>- The existing, top-level repeatElement(T, Int) function <i>could</i> stay, but could also be replaced with an incantation on CollectionOfOne. I’m fairly ambivalent about this point - it’d be nice to see the function go, but the replacement also isn’t obvious.</div><div><br></div><div>Example usage of the new API:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="Courier">// Equivalent to repeatElement(1, count: 3)</font></div><div><font face="Courier"><br></font></div><div><font face="Courier">&gt; for i in CollectionOfOne(1).repeatEleme<wbr>nts(3).forEach { print(i) }</font></div><div><font face="Courier">1</font></div><div><font face="Courier">1</font></div><div><font face="Courier">1</font></div><div><font face="Courier"><br></font></div><div><font face="Courier">// Equivalent to repeatElement([1, 2, 3], count: 3)</font></div><div><font face="Courier"><br></font></div><div><div><font face="Courier">&gt; for i in [1, 2, 3].repeated(3).forEach { print(i) }</font></div><div><font face="Courier">[1, 2, 3]</font></div><div><span style="font-family:Courier">[1, 2, 3]</span></div><div><span style="font-family:Courier">[1, 2, 3]</span></div></div><div><span style="font-family:Courier"><br></span></div><div><span style="font-family:Courier">// New, flat repetition</span></div><div><font face="Courier"><br></font></div><div><font face="Courier">&gt; for i in [1, 2, 3].repeatElements(3) { print(i) }</font></div><div><font face="Courier">1</font></div><div><font face="Courier">2</font></div><div><font face="Courier">3</font></div><div><font face="Courier">1</font></div><div><font face="Courier">2</font></div><div><font face="Courier">3</font></div><div><font face="Courier">1</font></div><div><font face="Courier">2</font></div><div><font face="Courier">3</font></div><div><font face="Courier"><br></font></div><div><div><span style="font-family:Courier">// New, flat repetition</span></div><div><font face="Courier"><br></font></div><div><font face="Courier">&gt; for i in [1, 2, 3].repeatElements(count: 4) { print(i) }</font></div><div><font face="Courier">1</font></div><div><font face="Courier">2</font></div><div><font face="Courier">3</font></div><div><font face="Courier">1</font></div><div><br></div></div><div><font face="Courier">// Additional benefit: you can now repeat slices!</font></div><div><font face="Courier"><br></font></div><div><font face="Courier">&gt; String(“yellow”.characters.dro<wbr>pFirst().dropLast().repeat(tim<wbr>es: 3))</font></div><div><font face="Courier">“elloelloello&quot;</font></div><div><br></div><div><br></div></blockquote>Thoughts?</div></div></blockquote><div><br></div><div>OK, now as to your proposed APIs themselves, here are some critiques:</div><div><br></div><div>The issue you&#39;ve identified with the cumbersome nature of CollectionOfOne shows why repeatElement is currently a top-level function and intentionally so. In brief, there&#39;s nothing special about Collection to make it the obvious type on which to provide a `repeated` method. The _result_ of that operation is a collection, but there&#39;s no reason the argument has to be. The correct &quot;type&quot; on which to provide that method would be Any, IMO, but of course we cannot provide extensions on Any. In general, in such scenarios, the consistent design choice in the standard library is to provide a free function.</div><div><br></div><div>Here, it is not inconsistent to _add_ something for repeating the elements in a collection (to Collection itself) without also stuffing the existing `repeatElement` functionality into Collection. TBH, the latter seems like an orthogonal topic included for the express purpose of eliminating top-level functions, without addressing the underlying reason for the existence of these top-level functions in the first place (no extensions on Any). So again, unrelated and worth setting aside, IMO.</div><div><br></div><div>Other minor points include that `repeatElements` doesn&#39;t meet standard API naming guidelines. It should be `repeatingElements`. You also intuitively tacked on a `times` argument label in the example usage even though your proposed API doesn&#39;t have it. It suggests that `repeat[ing]Elements(3)` is actually quite ambiguous: repeat the value 3, repeat the whole collection 3 times, or repeat so that the final count is 3? Better to have the label always, I should think. Another point is that it&#39;d take some justification to include both flavors of `repeat[ing]Elements`, as repeating until a final count is trivially composed with new one-sided ranges: `[1, 2, 3].repeatingElements(times: .max)[..&lt;4]`.</div><div><br></div><div><br></div></div></div></div>
</div></blockquote></div></div><span class=""><blockquote type="cite"><div><span>______________________________<wbr>_________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a></span><br></div></blockquote></span></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></div>