<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 class=""><br class=""></div><div class="">How important is it that the closure be allowed to throw when resolving collisions? In my use cases merging dictionaries he resolving of the collisions is always relatively simple. Shouldn’t they be as below maybe?</div><div class=""><br class=""></div><div class=""><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; background-color: rgb(246, 248, 250); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; color: rgb(36, 41, 46);" class=""> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"><span class="pl-c" style="box-sizing: border-box;">///</span> Creates a new dictionary using the key/value pairs in the given sequence,</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"><span class="pl-c" style="box-sizing: border-box;">///</span> using a combining closure to determine the value for any duplicate keys.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span><<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">S</span>: <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);"><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Sequence</span></span>>(
<span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">merging</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">keysAndValues</span>: S,
<span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">resolvingCollisionsWith</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">combine</span>: (<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>
) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">where</span> S.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Iterator</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Element</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Element</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"><span class="pl-c" style="box-sizing: border-box;">///</span> Merges the key/value pairs in the given sequence into the dictionary,</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"><span class="pl-c" style="box-sizing: border-box;">///</span> using a combining closure to determine the value for any duplicate keys.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">mutating</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">merge</span><<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">S</span>: <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);"><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Sequence</span></span>>(
<span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">_</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">other</span>: S,
<span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">resolvingCollisionsWith </span><span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">combine</span>: (<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>
) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">where</span> S.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Iterator</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Element</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Element</span></pre><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; background-color: rgb(246, 248, 250); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; color: rgb(36, 41, 46);" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; color: rgb(36, 41, 46);" class=""> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"><span class="pl-c" style="box-sizing: border-box;">///</span> Returns a new dictionary created by merging the key/value pairs in the</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"><span class="pl-c" style="box-sizing: border-box;">///</span> given sequence into the dictionary, using a combining closure to determine</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"><span class="pl-c" style="box-sizing: border-box;">///</span> the value for any duplicate keys.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">merged</span><<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">S</span>: <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);"><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Sequence</span></span>>(
<span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">with</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">other</span>: S,
<span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">resolvingCollisionsWith</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">combine</span>: (<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>
) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-></span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Key</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Value</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">where</span> S.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Iterator</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Element</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Element</span></pre></span></pre><div class=""><br class=""></div></div><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Apr 6, 2017, at 12:51 PM, Nate Cook 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=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Apr 5, 2017, at 9:43 PM, Brent Royal-Gordon 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=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class="">On Apr 5, 2017, at 5:45 PM, Ben Cohen via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;"><div class=""><div class=""><br class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>• What is your evaluation of the proposal?<br class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">(As a meta issue, I'm not sure I like the grab-bag review style; I'm finding this proposal a little bit difficult to navigate.)</div><div class=""><br class=""></div><div class=""><b class="">Sequence-based initializer and merging initializer</b></div><div class=""><br class=""></div><div class="">Good idea, but I think these two are redundant with each other, and I don't think "merging" is an accurate way to describe what the second one does. (`merging` would suggest to me that it was combining several dictionaries or lists, not combining conflicting elements.) I'd suggest a single initializer along the lines of:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>init<S: Sequence>(_ keysAndValues: S, correctingConflictsBy resolveConflict: (Value, Value) throws -> Value = { fatalError("Duplicate values \($0) and \($1)") }) rethrows</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>where S.Iterator.Element == (key: Key, value: Value)</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Thanks for all your feedback, Brent! One note on this item in particular—if you specify a default argument for a throws/rethrows closure, you have to use "try" at the call site even if the default closure argument doesn't throw. Modules currently don't promise that default closure arguments don't throw, and a default argument could change from non-throwing to throwing in a later version of a library.</div><div class=""><br class=""></div><div class="">There's a bug tracking the issue here: <a href="https://bugs.swift.org/browse/SR-2979" class="">https://bugs.swift.org/browse/SR-2979</a></div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><b class="">Merging methods</b></div><div class=""><br class=""></div><div class="">Good idea, but I'm not a fan of the `mergingValues:` label. I would suggest the same `correctingConflictsBy resolveConflict:` label I suggested for the previous method—possibly including the default value. I also think `merge(_:correctingConflictsBy:)`'s first parameter should be labeled `with`, just as the `merged` variant is.</div><div class=""><br class=""></div><div class="">I wonder if we might also want a method that copies the Dictionary, but with a single key added/removed/changed:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func withValue(_ value: Value?, forKey key: Key) -> [Key: Value]</div></div></div></div></blockquote><div class=""><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><b class="">Key-based subscript with default value</b></blockquote></div><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><br class=""></div><div class="">I like the functionality, but not way this proposal does it. I don't like having the default value be a labeled parameter to the subscript, because it isn't used to locate the value. However, I can't come up with a better syntax without adding language features. What I'd like to do is make it possible to assign through `??`:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>frequencies[c] ?? 0 += 1</div><div class=""><br class=""></div><div class="">But that would require either that we support `inout` functions, or that `??` become magic syntax instead of a standard library feature. The former is not coming in Swift 4 and the latter is less than ideal.</div><div class=""><br class=""></div><div class="">Still, if we would rather have that syntax and we think we'll soon have the language improvements needed to pull it off, I'd suggest rejecting this portion of the proposal.</div><div class=""><br class=""></div><div class=""><b class="">Dictionary-specific map and filter</b></div><div class=""><br class=""></div><div class="">I am +114 on this. I say that because I have received 114 upvotes on my Stack Overflow answer explaining how to write a `Dictionary.map` method: <<a href="http://stackoverflow.com/questions/24116271/whats-the-cleanest-way-of-applying-map-to-a-dictionary-in-swift/24219069#24219069" class="">http://stackoverflow.com/questions/24116271/whats-the-cleanest-way-of-applying-map-to-a-dictionary-in-swift/24219069#24219069</a>></div><div class=""><br class=""></div><div class="">I agree with the decision not to pass keys to the closures in these methods; that keeps them simple and focused, and ensures they stay parallel with ordinary `map` and `filter`. I also agree with the decision to not build in a form of `map` which allows key remapping; you can always do that with the sequence-based initializer, which would let you add conflict-handling logic more elegantly than a key-value `map` could.</div><div class=""><br class=""></div><div class=""><b class="">Visible dictionary capacity</b></div><div class=""><br class=""></div><div class="">I doubt I'll ever use the `capacity` property, but I'm not opposed to it. Adding a `reserveCapacity(_:)` method is a good idea.</div><div class=""><br class=""></div><div class=""><b class="">A grouped(by:) method for sequences</b></div><div class=""><br class=""></div><div class="">Yes, please.</div><div class=""><br class=""></div><div class=""><b class="">Apply relevant changes to Set</b></div><div class=""><br class=""></div><div class="">These make sense. (I considered suggesting the `filter` method be called `intersection(where:)`, but on second thought, I don't think that conveys the actual use cases for the method very well.)</div><div class=""><br class=""></div><div class="">I wonder if we might want to conform `Dictionary` to `SetAlgebra`. They have compatible semantics, and I've occasionally wanted to use them in the same places. On the other hand, some of the methods might form attractive nuisances; perhaps I should just write a SetAlgebra-conforming view when I want to do that.</div></div></div></blockquote><div class=""><blockquote type="cite" class=""><br class=""></blockquote></div><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><b class="">General notes</b></div><div class=""><b class=""><br class=""></b></div><div class="">If SE-0161 is accepted, we may want to support key path variants of some of these APIs (like `grouped(by:)`, `map(_:)`, and `filter(_:)`). On the other hand, we may want to defer that so we can consider that issue holistically, including with existing Collection APIs.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;"><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>• Is the problem being addressed significant enough to warrant a change to Swift?<br class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Yes. These are all common needs; when working with dictionaries, I find myself writing `for` loops with `var`s far more often than I'd like.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;"><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>• Does this proposal fit well with the feel and direction of Swift?<br class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Yes, these are all pretty straightforward additions.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;"><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>• If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?<br class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Ruby's `Hash` has many of these features and I appreciate them there; `NSDictionary` does not and it suffers for it. Perl hashes have a flattening behavior that tends to be amenable to editing them in various ways, but that's not really suitable for Swift.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;"><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>• How much effort did you put into your review? A glance, a quick reading, or an in-depth study?<br class=""></div></div></div></div></div></blockquote></div><div class=""><br class=""></div><div class="">Quick reading.</div><br class=""><div class=""><span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-east-asian: normal; font-variant-position: normal; line-height: normal; border-spacing: 0px;"><div class=""><div class="" style="font-size: 12px;">-- </div><div class="" style="font-size: 12px;">Brent Royal-Gordon</div><div class="" style="font-size: 12px;">Architechies</div></div></span></div><br class=""></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></div></body></html>