<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div>Below is my -1 on the proposal. But before that:</div><div><br class=""><blockquote type="cite" class=""><div class="">On 16 Feb 2016, at 20:26, Joe Groff via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I think a more expressive alternative approach to this problem would be to extend Dictionary with a `subscript(_:orDefault:)` member:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">extension Dictionary {</div><div class=""> subscript(key: Key, orDefault value: Value) -> Value { … }</div><div class="">}</div></blockquote></div></div></blockquote></div><div class=""><br class=""></div><div class="">I think it's really a shortcoming in <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">Dictionary</span>'s interface, where the general use case of updating a key in place usually asks for a lot of boilerplate. Thinking outside the box somewhat, one way to make all kinds of updates—"upserts", accumulating the value, but also removals—possible would be to extend <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">Optional</span>'s interface with this simple addition:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(187, 44, 162);" class="">extension<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Optional</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(187, 44, 162);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>public<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>mutating<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>func<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> rewrap(</span>@noescape<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> transform: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Wrapped</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">? </span>throws<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> -> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Wrapped</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">?) </span>rethrows<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span> = <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> transform(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span>)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><br class=""></div></div><div class="">Conditionally inserting a key would then be:</div><div class=""><br class=""></div><div class=""><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="color: rgb(187, 44, 162);" class="">var</span> dict = [2: "two"]</div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="color: rgb(79, 129, 135);" class="">dict</span>[<span style="color: rgb(39, 42, 216);" class="">1</span>].<span style="color: rgb(49, 89, 93);" class="">rewrap</span> {$0 ?? <span style="color: rgb(209, 47, 27);" class="">"one"</span>}</div></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">dict</span>[<span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">2</span>].<span style="color: rgb(49, 89, 93);" class="">rewrap</span> {$0 ?? <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"deux"</span>} <span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// no-op</span></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class="">// dict == [2: "two", 1: "one"]</div></div><div class=""><br class=""></div></div></div><div class="">Maintaining a set of counters:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; line-height: normal;" class=""><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> counts = [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">String</span>: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>]()</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> increment: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>? -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>? = {($0 ?? <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span>) + <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">1</span>}</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> decrement: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>? -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>? = {</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> n = ($0 ?? <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span>) - <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">1</span></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> n == <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span> ? <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">nil</span> : n</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal;" class="">}</div><div style="margin: 0px; line-height: normal;" class=""><font color="#4f8187" face="Menlo" class=""><span style="font-size: 11px;" class="">counts</span></font><span style="font-family: Menlo; font-size: 11px;" class="">[</span><font color="#d12f1b" face="Menlo" class=""><span style="font-size: 11px;" class="">"Söze"</span></font><span style="font-family: Menlo; font-size: 11px;" class="">].</span><span style="color: rgb(49, 89, 93); font-family: Menlo; font-size: 11px;" class="">rewrap</span><span style="font-family: Menlo; font-size: 11px;" class="">(</span><font color="#4f8187" face="Menlo" class=""><span style="font-size: 11px;" class="">increment</span></font><span style="font-family: Menlo; font-size: 11px;" class="">)</span></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal; color: rgb(79, 129, 135);" class="">counts<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">[</span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"Kujan"</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">].</span><span style="color: rgb(49, 89, 93);" class="">rewrap</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">(</span>increment<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">)</span></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal; color: rgb(79, 129, 135);" class="">counts<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">[</span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"Kint"</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">].</span><span style="color: rgb(49, 89, 93);" class="">rewrap</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">(</span>increment<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">)</span></div><div style="margin: 0px; line-height: normal;" class=""><font color="#4f8187" face="Menlo" style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">counts</font><span style="font-family: Menlo; font-size: 11px;" class="">[</span><span style="font-family: Menlo; font-size: 11px; color: rgb(209, 47, 27);" class="">"</span><font color="#d12f1b" face="Menlo" style="font-family: Menlo; font-size: 11px;" class="">Söze"</font><span style="font-family: Menlo; font-size: 11px;" class="">].</span><span style="font-family: Menlo; font-size: 11px; color: rgb(49, 89, 93);" class="">rewrap</span><span style="font-family: Menlo; font-size: 11px;" class="">(</span><font color="#4f8187" face="Menlo" style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">decrement</font><span style="font-family: Menlo; font-size: 11px;" class="">) </span><span style="font-family: Menlo; font-size: 11px; color: rgb(0, 132, 0);" class="">//</span><span style="font-family: Menlo; font-size: 11px; color: rgb(0, 132, 0);" class=""> poof… he's gone</span></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal; color: rgb(79, 129, 135);" class="">counts<span style="color: rgb(0, 0, 0);" class="">[</span><span style="color: rgb(209, 47, 27);" class="">"</span><span style="color: rgb(209, 47, 27);" class="">Kint</span><span style="color: rgb(209, 47, 27);" class="">"</span><span style="color: rgb(0, 0, 0);" class="">].</span><span style="color: rgb(49, 89, 93);" class="">rewrap</span><span style="color: rgb(0, 0, 0);" class="">(</span>increment<span style="color: rgb(0, 0, 0);" class="">)</span></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class="">// counts == ["Kujan": 1, "Kint": 2]</div><div style="font-family: Menlo; font-size: 11px;" class=""><br class=""></div><div class="">Originally I thought calling it simply <span style="color: rgb(49, 89, 93); font-family: Menlo; font-size: 11px;" class="">update</span>, however <span style="color: rgb(49, 89, 93); font-family: Menlo; font-size: 11px;" class="">rewrap</span> has a closer correspondence to <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">Optional</span>'s <span style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">Wrapped</span>, and might thus be less ambiguous.</div><div class=""><br class=""></div><div class="">— — —</div><div class=""><br class=""></div><div class="">What comes to the proposal then…</div><div style="font-family: Menlo; font-size: 11px;" class=""><br class=""></div></div></div><div class=""><div class=""><blockquote type="cite" class="">What is your evaluation of the proposal?<br class=""></blockquote><div class=""><br class=""></div>-1.<br class=""><br class=""></div><div class=""><blockquote type="cite" class="">Is the problem being addressed significant enough to warrant a change to Swift?<br class=""></blockquote><br class=""></div><div class="">I don't think this is the problem to be addressed. The issue here is that even after the update, the result is still an optional, so there's no promise that it'll have a non-<span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">nil</span> value. I have a feeling <span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">guard</span> could be used in most of these use cases for a better design. And lazy loading or set-once properties might help a bit too.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">Does this proposal fit well with the feel and direction of Swift?<br class=""></blockquote><br class=""></div><div class="">It's true that we have the in-place mutating <span style="font-family: Menlo; font-size: 11px;" class="">op=</span> variant of many operators <span style="font-family: Menlo; font-size: 11px;" class="">op</span> which happen to return the same type as their first argument. However, I see <span style="font-family: Menlo; font-size: 11px;" class="">??</span> as two overloads (<span style="font-family: Menlo; font-size: 11px;" class="">(</span><span style="font-family: Menlo; font-size: 11px; color: rgb(79, 129, 135);" class="">T</span><span style="font-family: Menlo; font-size: 11px;" class="">?, </span><span style="font-family: Menlo; font-size: 11px; color: rgb(79, 129, 135);" class="">T</span><span style="font-family: Menlo; font-size: 11px;" class="">) -> </span><span style="font-family: Menlo; font-size: 11px; color: rgb(79, 129, 135);" class="">T</span> and <span style="font-family: Menlo; font-size: 11px;" class="">(</span><span style="font-family: Menlo; font-size: 11px; color: rgb(79, 129, 135);" class="">T</span><span style="font-family: Menlo; font-size: 11px;" class="">?, </span><span style="font-family: Menlo; font-size: 11px; color: rgb(79, 129, 135);" class="">T</span><span style="font-family: Menlo; font-size: 11px;" class="">?) -> </span><span style="font-family: Menlo; font-size: 11px; color: rgb(79, 129, 135);" class="">T</span><span style="font-family: Menlo; font-size: 11px;" class="">?</span>), the one returning non-optional being the more official one which is somewhat against the current practice.</div><div class=""><br class=""></div><div class="">I also feel the use of this operator would leave too many <span style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">T</span><span style="font-family: Menlo; font-size: 11px;" class="">?</span> hanging around where <span style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">T</span> would do.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?<br class=""></blockquote><br class=""></div><div class="">Ruby comes in mind. Ruby is different in that it does nothing to prevent the Billion Dollar Mistake that they coincidentally call <span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">nil</span>.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">How much effort did you put into your review? A glance, a quick reading, or an in-depth study?</blockquote></div></div><div class=""><br class=""></div><div class="">I've followed the conversation for a couple of days and read through the proposal quickly. I've thought about the problem domain a lot before though.</div><div class=""><br class="webkit-block-placeholder"></div><div class=""><span class="Apple-style-span" style="border-collapse: separate; line-height: normal; border-spacing: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-variant: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; border-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px; font-size: 12px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">— Pyry Jahkola</div></span></div></span></div></body></html>