<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="">I think the idea of a combine closure is great - it lets users of the initialiser decide on whether or not the want duplicate keys to be an error. Also, the default “silently keep the last value” behaviour can be provided as the default closure. I also think that a closure (probably) gives enough flexibility to do most of the interesting things you might do with dictionaries (a “frequencies” function, or “categorise”, for instance).<div class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>Dictionary<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(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; </span>/// Creates a dictionary with the keys and values in the given sequence.</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; </span>/// Takes a closure which is called on the values of duplicate keys. The</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; </span>/// default behaviour is that the last value for a duplicate key is kept.</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&lt;S: </span>SequenceType<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>S<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span>Generator<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span>Element<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> == (</span>Key<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">,</span>Value<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">)&gt;</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; (<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span> sequence: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">S</span>, combine: (<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Value</span>,<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Value</span>) -&gt; <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Value</span> = { (<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span>,snd) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> snd } ) {</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="">&nbsp; &nbsp; </span>self<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span>init<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="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">for</span> (k,v) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> sequence {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span>[k] = <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span>[k].<span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">map</span> { fst <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> combine(fst,v) } ?? v</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; }</div><div class=""><span style="font-family: Menlo; font-size: 11px;" class="">}</span></div><div class=""><span style="font-family: Menlo; font-size: 11px;" class=""><br class=""></span></div><div class=""><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="">extension</span> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">SequenceType</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span> Generator.Element: Hashable {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> frequencies() -&gt; [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Generator</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Element</span>:<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>] {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Dictionary</span>(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">lazy</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">map</span> { v <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> (v,<span style="font-variant-ligatures: no-common-ligatures; color: #312cdd" class="">1</span>) }, combine: +)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; }</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; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 143, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #c93108" class="">"hello"</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">characters</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">frequencies</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">() </span>// ["e": 1, "o": 1, "l": 2, "h": 1]</div></div><div class=""><br class=""></div><div class="">&nbsp;<br class=""><div><blockquote type="cite" class=""><div class="">On 15 Jan 2016, at 10:53, Alan Skipp via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px; float: none; display: inline !important;" class="">I’ve been absorbed in the world of Monoids lately, so I find the suggestion below to be particularly brilliant. : )</span><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px;">It solves the issue of arbitrarily choosing the value for duplicate keys rather nicely. Only thing I’m not too sure about is the idea of failing by default on duplicate keys?</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px;"><div class=""><div class=""><blockquote type="cite" class=""><div class="">On 15 Jan 2016, at 10:18, Nicola Salmoria via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">To handle the case of duplicate keys, why not allow to pass in a 'combine' function?<br class="">The function could default to a preconditionFailure to be consistent with the DictionaryLiteral behavior, but be overridden by the caller as needed.<br class=""><br class="">extension Dictionary {<br class="">&nbsp;&nbsp;&nbsp; /// Creates a dictionary with the keys and values in the given sequence.<br class="">&nbsp;&nbsp;&nbsp; init&lt;S: SequenceType where S.Generator.Element == Generator.Element&gt;(_ sequence: S, combine: (existing: Value, other: Value) -&gt; Value = { preconditionFailure("Sequence contains duplicate keys"); return $1 } ) {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.init()<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (key, value) in sequence {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if let existing = updateValue(value, forKey: key) {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; updateValue(combine(existing: existing, other: value), forKey: key)<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br class="">&nbsp;&nbsp;&nbsp; }<br class="">}<br class=""><br class=""><br class="">usage examples:<br class=""><br class="">let samples = [("Rome", 40.2), ("New York", 35.1), ("Rome", 42.5), ("New York", 32.8)]<br class="">let minTemperatures = Dictionary(samples, combine: min)<br class="">// ["Rome": 40.2, "New York": 32.8]<br class="">let maxTemperatures = Dictionary(samples, combine: max)<br class="">// ["Rome": 42.5, "New York": 35.1]<br class=""><br class="">let probabilities = [("a", 0.25), ("b", 0.25), ("c", 0.25), ("a", 0.25)]<br class="">let stateProbabilities = Dictionary(probabilities, combine: +)<br class="">// ["b": 0.25, "a": 0.5, "c": 0.25]<br class=""><br class=""></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">Nicola</span></div></blockquote><br class=""></div><div class=""><div class="">It’d be great if there was also an init that restricted the Values to Monoids, which would mean the combine function would be taken from the supplied Monoid values (I understand I’ve departed to fantasy island at this point, but one can dream : )</div><div class=""><br class=""></div><div class="">Al<br class=""></div><div class=""><br class=""></div></div><br class=""></div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=Lo8TP3b1oIn3yQXUt9zA1UCQfR-2BMBCuqnubTuDg47-2B0lwPpApQV-2Fb2Nob4z6Hb3oToEFkpP9C71WzYCQTD5l0xoGp7bm1-2FypHn6e3WxUT90c-2BRGCz8iLYHjygIq7rYkqhRksgCb4pJ6rHt21doryrBRD75C5cthAXFG-2FSSApWiNh7gBz4mAka1q6C9BeGnPZgfrSoF-2BXl22r1swTfOeFM1DFiQdnubFJuTSmKtX1n3c-3D" alt="" width="1" height="1" border="0" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px; height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px; float: none; display: inline !important;" class=""><span class="Apple-converted-space">&nbsp;</span></span><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-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: 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-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-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: 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-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></div></body></html>