<div dir="ltr">+1 from me. Seems like a solid change.</div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 12, 2016 at 12:39 AM, Jacob Bandes-Storch 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="ltr">+1. Haven&#39;t hit this issue personally, but I agree it&#39;s important and the proposed solution seems like the right fix.<div class="gmail_extra">
<br><div class="gmail_quote"><div><div class="h5">On Tue, Oct 11, 2016 at 2:28 PM, Nate Cook 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></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div style="word-wrap:break-word"><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)">Introduction</h2><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">This proposal addresses significant unexpected performance gaps when using dictionaries. It introduces type-specific collections for a <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Dictionary</code> instance&#39;s <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">keys</code> a<wbr>nd <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">values</code> properties.</p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">New <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryKeys</code> and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Diction<wbr>aryValues</code> collections provide efficient key lookup and mutable access to dictionary values, enabling updates to be performed in-place and allowing copy-on-write optimization of stored values.</p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a id="m_2782616848335775716m_-5298482864340174762user-content-motivation" class="m_2782616848335775716m_-5298482864340174762anchor" href="https://gist.github.com/natecook1000/473720ba072fa5a0cd5e6c913de75fe1#motivation" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Motivation</h2><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">This proposal address two problems:</p><ul style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li style="box-sizing:border-box">The Dictionary type <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">keys</code> implementation is inefficient, because <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">LazyMapCollection</code> does<wbr>n&#39;t know how to forward lookups to the underlying dictionary storage.</li><li style="box-sizing:border-box;margin-top:0.25em">Dictionaries do not offer value-mutating APIs. The mutating key-based subscript wraps values in an <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Optional</code>. This prevents types with copy-on-write optimizations from recognizing they are singly referenced.</li></ul><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">This proposal uses the following <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">[String: [Int]]</code> dictionary to demonstrate these problems:</p><div class="m_2782616848335775716m_-5298482864340174762highlight m_2782616848335775716m_-5298482864340174762highlight-source-swift" style="box-sizing:border-box;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> dict <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> [<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>: [<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">1</span>], <span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>two<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>: [<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">2</span>, <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">2</span>], <span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>three<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>: [<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">3</span>, <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">3</span>, <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">3</span>]]</pre></div><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a id="m_2782616848335775716m_-5298482864340174762user-content-inefficient-dictkeys-search" class="m_2782616848335775716m_-5298482864340174762anchor" href="https://gist.github.com/natecook1000/473720ba072fa5a0cd5e6c913de75fe1#inefficient-dictkeys-search" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Inefficient <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:inherit;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">dict.keys</code> Search</h3><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Swift coders normally test key membership using <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">nil</code> checks or underscored optional bindings:</p><div class="m_2782616848335775716m_-5298482864340174762highlight m_2782616848335775716m_-5298482864340174762highlight-source-swift" style="box-sizing:border-box;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> dict[<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>] <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">!=</span> <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">nil</span> {
    <span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// ...</span>
}
<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> _ <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> dict[<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>] {
    <span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// ...</span>
}</pre></div><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">These approaches provide the expected performance of a dictionary lookup but they read neither well nor &quot;Swifty&quot;. Checking <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">keys</code> reads much better but introduces a serious performance penalty: this approach requires a linear search through a dictionary&#39;s keys to find a match.</p><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:16px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;color:rgb(51,51,51)"><code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;padding:0px;margin:0px;background-color:transparent;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;border:0px;display:inline;overflow:visible;line-height:inherit;word-wrap:normal">if dict.keys.contains(&quot;one&quot;) {
    // ...
}
</code></pre><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">A similar dynamic plays out when comparing <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">dict.index(forKey:)</code> <wbr>and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">dict.keys.index(of:)</code>.</p><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a id="m_2782616848335775716m_-5298482864340174762user-content-inefficient-value-mutation" class="m_2782616848335775716m_-5298482864340174762anchor" href="https://gist.github.com/natecook1000/473720ba072fa5a0cd5e6c913de75fe1#inefficient-value-mutation" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Inefficient Value Mutation</h3><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Dictionary values can be modified through the keyed subscript by direct reassignment or by using optional chaining. Both of these statements append <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">1</code> to the array stored by the key <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">&quot;one&quot;</code>:</p><div class="m_2782616848335775716m_-5298482864340174762highlight m_2782616848335775716m_-5298482864340174762highlight-source-swift" style="box-sizing:border-box;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// Direct re-assignment</span>
dict[<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>] <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> (dict[<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>] <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">??</span> []) <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">+</span> [<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">1</span>]

<span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// Optional chaining</span>
dict[<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>]?<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span>append(<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">1</span>)</pre></div><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Both approaches present problems. The first is complex and hard to read. The second ignores the case where <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">&quot;one&quot;</code> is not a key in the dictionary. It forces its check into a higher branch and encourages forced unwrapping. Furthermore, neither approach allows the array to grow in place. They introduce an unnecessary copy of the array&#39;s contents even though <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">dict</code> is the sole holder of its storage.</p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Adding mutation to a dictionary&#39;s index-based subscripting isn&#39;t possible. Changing a key stored at a particular index would almost certainly modify its hash value, rendering the index incorrect. This violates the requirements of the <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">MutableCollection</code> protocol<wbr>.</p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a id="m_2782616848335775716m_-5298482864340174762user-content-proposed-solution" class="m_2782616848335775716m_-5298482864340174762anchor" href="https://gist.github.com/natecook1000/473720ba072fa5a0cd5e6c913de75fe1#proposed-solution" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Proposed Solution</h2><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">This proposal adds a custom collection for the <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">keys</code> and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">values</code> dictionary properties. This follows the example set by <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">String</code>, which presents multiple views of its contents. A new <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryKeys</code> collection introduces efficient key lookup, while a new <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryValues</code> collectio<wbr>n provides a mutable collection interface to dictionary values.</p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">These changes introduce a simple and efficient way of checking whether a dictionary includes a key:</p><div class="m_2782616848335775716m_-5298482864340174762highlight m_2782616848335775716m_-5298482864340174762highlight-source-swift" style="box-sizing:border-box;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// Performant</span>
<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> dict<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span><span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">keys</span><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span><span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">contains</span>(<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>) {
    <span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// ...</span>
}</pre></div><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">As a mutable collection, <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">values</code> enables modification without copies or clumsy code:</p><div class="m_2782616848335775716m_-5298482864340174762highlight m_2782616848335775716m_-5298482864340174762highlight-source-swift" style="box-sizing:border-box;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> i <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> dict<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span>index(forKey: <span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>) {
    dict<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span><span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">values</span>[i]<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span>append(<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">1</span>)  <span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// no copy here</span>
} <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">else</span> {
    dict[<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>] <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> [<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">1</span>]
}</pre></div><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Both the <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">keys</code> and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">values</code> collection<wbr>s share the same index type as <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Dictionary</code>. This allows the above sample to be rewritten as:</p><div class="m_2782616848335775716m_-5298482864340174762highlight m_2782616848335775716m_-5298482864340174762highlight-source-swift" style="box-sizing:border-box;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// Using `dict.keys.index(of:)`</span>
<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> i <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> dict<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span><span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">keys</span><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span>index(of: <span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>) {
    dict<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span><span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">values</span>[i]<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">.</span>append(<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">1</span>)
} <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">else</span> {
    dict[<span class="m_2782616848335775716m_-5298482864340174762pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span>one<span class="m_2782616848335775716m_-5298482864340174762pl-pds" style="box-sizing:border-box">&quot;</span></span>] <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> [<span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">1</span>]
}</pre></div><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a id="m_2782616848335775716m_-5298482864340174762user-content-detailed-design" class="m_2782616848335775716m_-5298482864340174762anchor" href="https://gist.github.com/natecook1000/473720ba072fa5a0cd5e6c913de75fe1#detailed-design" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Detailed design</h2><ul style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li style="box-sizing:border-box">The standard library introduces two new collection types: <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryKeys</code> and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Dict<wbr>ionaryValues</code>.</li><li style="box-sizing:border-box;margin-top:0.25em">A <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Dictionary</code>&#39;s <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">keys</code> and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">values</code><wbr> property types change from <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">LazyMapCollection</code> to these new types. </li><li style="box-sizing:border-box;margin-top:0.25em">The new collection types are not directly constructable. They are presented only as views into a dictionary.</li></ul><div class="m_2782616848335775716m_-5298482864340174762highlight m_2782616848335775716m_-5298482864340174762highlight-source-swift" style="box-sizing:border-box;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">struct</span> <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">Dictionary</span><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&lt;</span>Key: <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">Hashable</span>, Value<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&gt;</span>: <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">...</span> {
    <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> keys: DictionaryKeys<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&lt;</span>Key, Value<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&gt;</span> { <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">get</span> }
    <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> values: DictionaryValues<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&lt;</span>Key, Value<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&gt;</span> { <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">get</span> <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">set</span> }

    <span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// Remaining declarations</span>
}

<span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">/// A collection view of a dictionary&#39;s keys.</span>
<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">struct</span> DictionaryKeys<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&lt;</span>Key: <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">Hashable</span>, Value<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&gt;</span>: Collection {
    <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">typealias</span> Index <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">DictionaryIndex</span><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&lt;</span>Key, Value<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&gt;</span>
    <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">subscript</span>(i: Index) <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">-&gt;</span> Key { <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">get</span> }

    <span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// Other `Collection` requirements</span>
}

<span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">/// A mutable collection view of a dictionary&#39;s values.</span>
<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">struct</span> DictionaryValues<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&lt;</span>Key: <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">Hashable</span>, Value<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&gt;</span>: MutableCollection {
    <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">typealias</span> Index <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> <span class="m_2782616848335775716m_-5298482864340174762pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">DictionaryIndex</span><span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&lt;</span>Key, Value<span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">&gt;</span>
    <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">subscript</span>(i: Index) <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">-&gt;</span> Value { <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">get</span> <span class="m_2782616848335775716m_-5298482864340174762pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">set</span> }

    <span class="m_2782616848335775716m_-5298482864340174762pl-c" style="box-sizing:border-box;color:rgb(150,152,150)">// Other `Collection` requirements</span>
}</pre></div><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">A sample implementation of this proposal can be found in <a href="https://github.com/natecook1000/swift/tree/nc-dictionary" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">this branch</a>.</p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a id="m_2782616848335775716m_-5298482864340174762user-content-impact-on-existing-code" class="m_2782616848335775716m_-5298482864340174762anchor" href="https://gist.github.com/natecook1000/473720ba072fa5a0cd5e6c913de75fe1#impact-on-existing-code" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Impact on existing code</h2><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">The performance improvements of using the new <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryKeys</code> type and the mutability of the <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryValues</code>collection are both additive in nature.</p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Most uses of these properties are transitory in nature. Adopting this proposal should not produce a major impact on existing code. The only impact on existing code exists where a program explicitly specifies the type of a dictionary&#39;s <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">keys</code>or <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">values</code> pro<wbr>perty. The fix is to change the specified type. </p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a id="m_2782616848335775716m_-5298482864340174762user-content-alternatives-considered" class="m_2782616848335775716m_-5298482864340174762anchor" href="https://gist.github.com/natecook1000/473720ba072fa5a0cd5e6c913de75fe1#alternatives-considered" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Alternatives considered</h2><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">The <a href="https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md" style="box-sizing:border-box;background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Generics Manifesto</a> lists nested generics as a goal. This could impact the naming and structure of these new collection types. </p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Instead of <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryKeys&lt;Key, Value&gt;</code> and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryValues&lt;Ke<wbr>y, Value&gt;</code>, these types could be <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Dictionary&lt;Key, Value&gt;.Keys</code> and <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">Dictionary&lt;Key<wbr>, Value&gt;.Values</code>. However, because many types in the standard library may be revisited once such a feature is available (indices, iterators, etc.), the current lack of nesting shouldn&#39;t prevent consideration of this proposal.</p><div style="box-sizing:border-box;margin-top:0px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Helvetica,Arial,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255);margin-bottom:0px!important">It could be possible to add additional compiler features that manage mutation through existing key-based subscripting without the copy-on-write problems of the current implementation. I don&#39;t know enough about how that would be implemented to speak to its feasibility or level of effort. Such a feature would reduce the need for a mutable <code style="box-sizing:border-box;font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;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">DictionaryValues</code> colle<wbr>ction.</div></div><br></div></div><span class="">______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></span></blockquote></div><br></div></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>