<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Hi swift-evolution,</div><div class=""><br class=""></div><div class="">Another short proposal related to the Collection algorithms theme, this time for removing elements in-place from a collection.</div><div class=""><br class=""></div><div class="">Online copy here: <a href="https://github.com/airspeedswift/swift-evolution/blob/1aac5593828941431d1805503865e7a2913d538b/proposals/NNNN-RemoveWhere.md" class="">https://github.com/airspeedswift/swift-evolution/blob/1aac5593828941431d1805503865e7a2913d538b/proposals/NNNN-RemoveWhere.md</a></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><h1 id="adding-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; position: relative; 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="">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="">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=""><li style="box-sizing: border-box;" class="">Proposal: <a href="file:///Users/ben_cohen/Documents/swift-evolution/proposals/NNNN-filename.md" style="box-sizing: border-box; background-color: transparent; color: rgb(65, 131, 196); text-decoration: none;" class="">SE-NNNN</a></li><li style="box-sizing: border-box;" class="">Authors: <a href="https://github.com/airspeedswift" style="box-sizing: border-box; background-color: transparent; color: rgb(65, 131, 196); text-decoration: none;" class="">Ben Cohen</a></li><li style="box-sizing: border-box;" class="">Review Manager: TBD</li><li style="box-sizing: border-box;" class="">Status: <strong style="box-sizing: border-box;" class="">Awaiting review</strong></li></ul><h2 id="introduction" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">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="">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="">Equatable</code> value, or match that a certain criteria.</p><h2 id="motivation" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">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="">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="">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="">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; tab-size: 4; color: rgb(51, 51, 51); height: 88px;" class=""><code class="swift hljs" 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="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">var</span> nums = [<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">1</span>,<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">2</span>,<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">3</span>,<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">4</span>,<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">5</span>]
<span class="hljs-comment" style="box-sizing: border-box; color: rgb(153, 153, 136); font-style: italic;">// remove odd elements</span>
nums = nums.<span class="hljs-built_in" style="box-sizing: border-box; color: rgb(0, 134, 179);">filter</span> { !isOdd($<span class="hljs-number" 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="">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="">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="">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; tab-size: 4; color: rgb(51, 51, 51); height: 223px;" class=""><code class="swift hljs" 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="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">var</span> i = nums.index(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">where</span>: isOdd) {
<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">var</span> j = i + <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">1</span>
<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">while</span> j != nums.endIndex {
<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">let</span> e = nums[j]
<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span> !isOdd(nums[j]) {
nums[i] = nums[j]
i += <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">1</span>
}
j += <span class="hljs-number" 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="">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="">Additionally, this approach does not work for range-replaceable collections that are <em style="box-sizing: border-box;" class="">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="">String</code> is the most important example of this, because its elements (graphemes) are variable width.</p><h2 id="proposed-solution" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">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="">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; tab-size: 4; color: rgb(51, 51, 51); height: 73px;" class=""><code class="swift hljs" 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="hljs-number" style="box-sizing: border-box; color: rgb(0, 128, 128);">9</span>)
nums.removeAll(<span class="hljs-keyword" 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="">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="">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="">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="">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="">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="">Collections which are range replaceable but <em style="box-sizing: border-box;" class="">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="">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="">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="">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="">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="">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="detailed-design" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">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="">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; tab-size: 4; color: rgb(51, 51, 51); height: 178px;" class=""><code class="swift hljs" 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="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">protocol</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(68, 85, 136); font-weight: bold;">RangeReplaceableCollection</span> </span>{
<span class="hljs-comment" 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="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">mutating</span> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">func</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(153, 0, 0); font-weight: bold;">removeAll</span><span class="hljs-params" style="box-sizing: border-box;">(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">where</span>: <span class="hljs-params" style="box-sizing: border-box;">(Iterator.Element)</span></span></span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">throws</span> -> <span class="hljs-type" style="box-sizing: border-box; color: rgb(68, 85, 136); font-weight: bold;">Bool</span>) <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">rethrows</span>
}
<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">extension</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(68, 85, 136); font-weight: bold;">RangeReplaceableCollection</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(68, 85, 136); font-weight: bold;">where</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(68, 85, 136); font-weight: bold;">Iterator</span>.<span class="hljs-title" style="box-sizing: border-box; color: rgb(68, 85, 136); font-weight: bold;">Element</span>: <span class="hljs-title" style="box-sizing: border-box; color: rgb(68, 85, 136); font-weight: bold;">Equatable</span> </span>{
<span class="hljs-comment" 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="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">mutating</span> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">func</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(153, 0, 0); font-weight: bold;">removeAll</span><span class="hljs-params" style="box-sizing: border-box;">(equalTo element: Iterator.Element)</span></span>
}</code></pre><h2 id="source-compatibility" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">This change is purely additive so has no source compatibility consequences.</p><h2 id="effect-on-abi-stability" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">This change is purely additive so has no ABI stability consequences.</p><h2 id="effect-on-api-resilience" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">This change is purely additive so has no API resilience consequences.</p><h2 id="alternatives-considered" style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; 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="">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="">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="">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="">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="">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="">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="">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="">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="">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=""><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="">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="">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="">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="">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="">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=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>