<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Oct 12, 2016 at 10:31 AM, Nate Cook via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Thanks for your feedback! Response below.<div><br><div><span class=""><blockquote type="cite"><div>On Oct 12, 2016, at 5:40 AM, Daniel Vollmer via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_-2838708742513182122Apple-interchange-newline"><div><div>Hi,<br><br>I very much think the points mentioned in the motivation are worth addressing (and IMO this is not an area where “maybe the optimizer can be made smarter” can cut it; I want performance guarantees, not hopes).<br><br><blockquote type="cite">On 11 Oct 2016, at 23:28, Nate Cook via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br></blockquote><br>[snip]<br><br>On a shallow read I like presented approach, except for<br><br><blockquote type="cite">Both the keys and values collections share the same index type as Dictionary. This allows the above sample to be rewritten as:<br><br>// Using `dict.keys.index(of:)`<br>if let i = dict.keys.index(of: "one") {<br> dict.values[i].append(1)<br>} else {<br> dict["one"] = [1]<br>}<br></blockquote><br>The asymmetry between the if / else branches seems ugly to me. That is once obtaining the value “directly” from dict, and once through the values-view. I don’t have a great solution here, but is is possible to subscript the dict by its `Index` as well as its `Key`?<br><br>```<br>// Using `dict.keys.index(of:)`<br>if let i = dict.keys.index(of: "one") {<br> dict[i].append(1)<br>} else {<br> dict["one"] = [1]<br>}<br>```<br></div></div></blockquote><div><br></div></span><div>I share your concern with this, and there is an approach that would make this kind of interface possible. Basically, what you're describing here would necessitate changing Dictionary to act like a mutable collection of values, and instead of presenting `keys` and `values` views, we would probably offer `keys` and `keysAndValues` (or something) views. With that new model, we'd have code like the following:</div><div><br></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><span class=""><div><div><div>var dict = ["one": [1], "two": [2, 2], "three": [3, 3, 3]]</div></div></div><div><div><div><br></div></div></div></span><div><div><div>// Iterating the dictionary itself would be like we now iterate the values collection</div></div></div><div><div><div>for val in dict {</div></div></div><div><div><div><span class="m_-2838708742513182122Apple-tab-span" style="white-space:pre-wrap">        </span>print(val)</div></div></div><div><div><div>}</div></div></div><div><div><div>// Output is just the values (unordered as usual)</div></div></div><div><div><div>// [1]</div></div></div><div><div><div>// [3, 3, 3]</div></div></div><div><div><div>// [2, 2]</div></div></div><div><div><div><br></div></div></div><div><div><div>// Iterating a new view would act like the dictionary currently does</div></div></div><div><div><div>for (key, val) in dict.keysAndValues {</div></div></div><div><div><div><span class="m_-2838708742513182122Apple-tab-span" style="white-space:pre-wrap">        </span>print(key, val)</div></div></div><div><div><div>}</div></div></div><div><div><div>// "one", [1]</div></div></div><div><div><div>// "three", [3, 3, 3]</div></div></div><div><div><div>// "two", [2, 2]</div></div></div></blockquote><div><div><div><br></div><div>Any sequence or collections operations on the dictionary itself would only interact with values:</div><div><br></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div>print(dict.first)</div></div></div><div><div><div>// Optional([1])</div></div></div><div><div><div>print(dict.first(where: { $0.count > 2 }))</div></div></div><div><div><div>// Optional([3, 3, 3])</div></div></div></blockquote><div><div><br></div><div>I'm not strictly opposed to this approach, but I do prefer the way the current dictionary implementation presents its elements as key-value pairs. When you iterate a dictionary you're seeing <i>all</i> of its contents, which I like, but there are clear tradeoffs between the two. Making Dictionary a collection of values is also a much more significant change than the one proposed—we'd need to do some research into the ways dictionaries are used to know how much larger an effect that would be.</div><div><br></div><div>What do others think of this as an alternative solution for the motivating issues? Does anyone actually use indices right now to work with dictionaries, or is key-based read/write pretty much the only interface?</div></div></div></blockquote><div><br></div><div>I much, much prefer your proposed solution to this alternative. Most of it is just a gut reaction, I have to admit. However, let me try to verbalize some reasons:</div><div><br></div><div>For one, the performance issues are the motivating problem, and they are solved with minimal disruption to the current Dictionary API in your currently proposed solution. Second, I think the asymmetry identified (while aesthetically less than perfectly pleasing) is in the nature of opaque indices and is consistent with precedent in String. Finally, I think it's ideal that we can introduce collection types to learners by pointing out that arrays are notionally index-based and dictionaries are key-based (however these types are actually implemented behind the scenes); permitting direct subscripting by dictionary indices muddies that distinction.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><span class=""><blockquote type="cite"><div><div>On another note, I’m not sure whether there is a way (or whether it’s even worth trying) to avoid hashing the key twice when the `else` branch is taken.<br></div></div></blockquote><div><br></div></span><div>This is outside the scope of the proposal, but as far as I can see I don't think there's a solution for this that wouldn't overly expose the internal workings of the dictionary.</div></div><br></div><div>Thanks again,</div><div>Nate</div><div><br></div><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></div>