+1. Perfect. Let's not bikeshed this and get it done!<br><div class="gmail_quote"><div dir="ltr">On Sat, Apr 8, 2017 at 14:04 Ben Cohen via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Hi swift-evolution,</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Another short proposal related to the Collection algorithms theme, this time for removing elements in-place from a collection.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Online copy here: <a href="https://github.com/airspeedswift/swift-evolution/blob/1aac5593828941431d1805503865e7a2913d538b/proposals/NNNN-RemoveWhere.md" class="gmail_msg" target="_blank">https://github.com/airspeedswift/swift-evolution/blob/1aac5593828941431d1805503865e7a2913d538b/proposals/NNNN-RemoveWhere.md</a></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><h1 id="m_7129395808333642964adding-in-place--code-removeall--code--to-the-standard-library" style="box-sizing:border-box;font-size:2.25em;margin-right:0px;margin-bottom:16px;margin-left:0px;line-height:1.2;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255);margin-top:0px!important" class="gmail_msg">Adding in-place <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:24.479999542236328px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">removeAll</code> to the Standard Library</h1><ul style="box-sizing:border-box;padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg"><li style="box-sizing:border-box" class="gmail_msg">Proposal: <a style="box-sizing:border-box;background-color:transparent;color:rgb(65,131,196);text-decoration:none" class="gmail_msg">SE-NNNN</a></li><li style="box-sizing:border-box" class="gmail_msg">Authors: <a href="https://github.com/airspeedswift" style="box-sizing:border-box;background-color:transparent;color:rgb(65,131,196);text-decoration:none" class="gmail_msg" target="_blank">Ben Cohen</a></li><li style="box-sizing:border-box" class="gmail_msg">Review Manager: TBD</li><li style="box-sizing:border-box" class="gmail_msg">Status: <strong style="box-sizing:border-box" class="gmail_msg">Awaiting review</strong></li></ul><h2 id="m_7129395808333642964introduction" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Introduction</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">It is common to want to remove all occurrences of a certain element from a collection. This proposal is to add two in-place <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">remove</code> algorithms to the standard library, which will remove all entries in a collection in-place matching either an <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">Equatable</code> value, or match that a certain criteria.</p><h2 id="m_7129395808333642964motivation" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Motivation</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Removing all elements matching some criteria is a very common operation. However, it can be tricky to implement correctly and efficiently.</p><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">The easiest way to achieve this effect in Swift 3 is to use <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">filter</code> and assign back, negating the thing you want to remove (because <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">filter</code> takes a closure of items to “keep”):</p><pre style="box-sizing:border-box;overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;margin-top:0px;margin-bottom:16px;font-stretch:normal;line-height:1.45;padding:16px;background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;color:rgb(51,51,51);height:88px" class="gmail_msg"><code class="m_7129395808333642964swift m_7129395808333642964hljs gmail_msg" style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0.5em;margin:0px;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;border:0px;display:block;overflow-x:auto;line-height:inherit;word-wrap:normal;height:auto"><span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">var</span> nums = [<span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">1</span>,<span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">2</span>,<span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">3</span>,<span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">4</span>,<span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">5</span>]
<span class="m_7129395808333642964hljs-comment gmail_msg" style="box-sizing:border-box;color:rgb(153,153,136);font-style:italic">// remove odd elements</span>
nums = nums.<span class="m_7129395808333642964hljs-built_in gmail_msg" style="box-sizing:border-box;color:rgb(0,134,179)">filter</span> { !isOdd($<span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">0</span>) }</code></pre><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">In addition to readability concerns, this has two performance problems: fresh memory allocation, and a copy of all the elements in full even if none need to be removed.</p><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">The alternative is to open-code a <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">for</code> loop. The simplest performant solution is the “shuffle-down” approach. While not especially complex, it is certainly non-trivial:</p><pre style="box-sizing:border-box;overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;margin-top:0px;margin-bottom:16px;font-stretch:normal;line-height:1.45;padding:16px;background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;color:rgb(51,51,51);height:223px" class="gmail_msg"><code class="m_7129395808333642964swift m_7129395808333642964hljs gmail_msg" style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0.5em;margin:0px;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;border:0px;display:block;overflow-x:auto;line-height:inherit;word-wrap:normal;height:auto"><span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">if</span> <span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">var</span> i = nums.index(<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">where</span>: isOdd) {
<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">var</span> j = i + <span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">1</span>
<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">while</span> j != nums.endIndex {
<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">let</span> e = nums[j]
<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">if</span> !isOdd(nums[j]) {
nums[i] = nums[j]
i += <span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">1</span>
}
j += <span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">1</span>
}
nums.removeSubrange(i..<nums.endIndex)
}</code></pre><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Possibilities for logic and performance errors abound. There are probably some in the above code.</p><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Additionally, this approach does not work for range-replaceable collections that are <em style="box-sizing:border-box" class="gmail_msg">not</em> mutable i.e. collections that can replace subranges, but can’t guarantee replacing a single element in constant time. <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">String</code> is the most important example of this, because its elements (graphemes) are variable width.</p><h2 id="m_7129395808333642964proposed-solution" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Proposed solution</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Add the following methods to <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">RangeReplaceableCollection</code>:</p><pre style="box-sizing:border-box;overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;margin-top:0px;margin-bottom:16px;font-stretch:normal;line-height:1.45;padding:16px;background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;color:rgb(51,51,51);height:73px" class="gmail_msg"><code class="m_7129395808333642964swift m_7129395808333642964hljs gmail_msg" style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0.5em;margin:0px;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;border:0px;display:block;overflow-x:auto;line-height:inherit;word-wrap:normal;height:auto">nums.removeAll(equalTo: <span class="m_7129395808333642964hljs-number gmail_msg" style="box-sizing:border-box;color:rgb(0,128,128)">9</span>)
nums.removeAll(<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">where</span>: isOdd)</code></pre><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">The default implementation will use the protocol’s <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">init()</code> and <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">append(_:)</code> operations to implement a copy-based version. Collections which also conform to <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">MutableCollection</code> will get the more efficient “shuffle-down” implementation, but still require <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">RangeReplaceableCollection</code> as well because of the need to trim at the end.</p><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Collections which are range replaceable but <em style="box-sizing:border-box" class="gmail_msg">not</em> mutable (like <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">String</code>) will be able to implement their own version which makes use of their internal layout. Collections like <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">Array</code> may also implement more efficient versions using memory copying operations.</p><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Since <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">Dictionary</code> and <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">Set</code> would benefit from this functionality as well, but are not range-replaceable, they should be given concrete implementations for consistency.</p><h2 id="m_7129395808333642964detailed-design" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Detailed design</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Add the following to <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">RangeReplaceableCollection</code>:</p><pre style="box-sizing:border-box;overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;margin-top:0px;margin-bottom:16px;font-stretch:normal;line-height:1.45;padding:16px;background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;color:rgb(51,51,51);height:178px" class="gmail_msg"><code class="m_7129395808333642964swift m_7129395808333642964hljs gmail_msg" style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0.5em;margin:0px;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;border:0px;display:block;overflow-x:auto;line-height:inherit;word-wrap:normal;height:auto"><span class="m_7129395808333642964hljs-class gmail_msg" style="box-sizing:border-box"><span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">protocol</span> <span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(68,85,136);font-weight:bold">RangeReplaceableCollection</span> </span>{
<span class="m_7129395808333642964hljs-comment gmail_msg" style="box-sizing:border-box;color:rgb(153,153,136);font-style:italic">/// Removes every element satisfying the given predicate from the collection.</span>
<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">mutating</span> <span class="m_7129395808333642964hljs-function gmail_msg" style="box-sizing:border-box"><span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">func</span> <span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(153,0,0);font-weight:bold">removeAll</span><span class="m_7129395808333642964hljs-params gmail_msg" style="box-sizing:border-box">(<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">where</span>: <span class="m_7129395808333642964hljs-params gmail_msg" style="box-sizing:border-box">(Iterator.Element)</span></span></span> <span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">throws</span> -> <span class="m_7129395808333642964hljs-type gmail_msg" style="box-sizing:border-box;color:rgb(68,85,136);font-weight:bold">Bool</span>) <span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">rethrows</span>
}
<span class="m_7129395808333642964hljs-class gmail_msg" style="box-sizing:border-box"><span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">extension</span> <span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(68,85,136);font-weight:bold">RangeReplaceableCollection</span> <span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(68,85,136);font-weight:bold">where</span> <span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(68,85,136);font-weight:bold">Iterator</span>.<span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(68,85,136);font-weight:bold">Element</span>: <span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(68,85,136);font-weight:bold">Equatable</span> </span>{
<span class="m_7129395808333642964hljs-comment gmail_msg" style="box-sizing:border-box;color:rgb(153,153,136);font-style:italic">/// Removes every element equal to the given element from the collection.</span>
<span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">mutating</span> <span class="m_7129395808333642964hljs-function gmail_msg" style="box-sizing:border-box"><span class="m_7129395808333642964hljs-keyword gmail_msg" style="box-sizing:border-box;font-weight:bold">func</span> <span class="m_7129395808333642964hljs-title gmail_msg" style="box-sizing:border-box;color:rgb(153,0,0);font-weight:bold">removeAll</span><span class="m_7129395808333642964hljs-params gmail_msg" style="box-sizing:border-box">(equalTo element: Iterator.Element)</span></span>
}</code></pre><h2 id="m_7129395808333642964source-compatibility" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Source compatibility</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">This change is purely additive so has no source compatibility consequences.</p><h2 id="m_7129395808333642964effect-on-abi-stability" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Effect on ABI stability</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">This change is purely additive so has no ABI stability consequences.</p><h2 id="m_7129395808333642964effect-on-api-resilience" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Effect on API resilience</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">This change is purely additive so has no API resilience consequences.</p><h2 id="m_7129395808333642964alternatives-considered" style="box-sizing:border-box;margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;color:rgb(51,51,51);padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);font-family:helvetica,arial,freesans,clean,sans-serif;background-color:rgb(255,255,255)" class="gmail_msg">Alternatives considered</h2><p style="box-sizing:border-box;margin:0px 0px 16px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255)" class="gmail_msg">Regarding the name: <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">remove</code> instead of <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">removeAll</code> was considered. <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">removeAll(equalTo: 5)</code> seems clearer when seen alongside similar methods <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">removeFirst(5)</code> and <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">remove(at: 5)</code>. In the case of <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">remove(where:)</code>, the <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">All</code> in the basename is preserved for trailing closures.</p><div style="box-sizing:border-box;margin-top:0px;margin-right:0px;margin-left:0px;color:rgb(51,51,51);font-family:helvetica,arial,freesans,clean,sans-serif;font-size:12.799999237060547px;background-color:rgb(255,255,255);margin-bottom:0px!important" class="gmail_msg"><code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">removeAll(where:)</code> takes a closure with <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">true</code> for elements to remove. <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">filter</code> takes a closure with elements to keep. In both cases, <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">true</code> is the “active” case, so likely to be what the user wants without having to apply a negation. The naming of <code style="box-sizing:border-box;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10.880000114440918px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="gmail_msg">filter</code> is unfortunately ambiguous as to whether it’s a removing or keeping operation, but re-considering that is outside the scope of this proposal.</div></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div></div>_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div>