[swift-evolution] [Proposal Draft] Provide Custom Collections for Dictionary Keys and Values

Xiaodi Wu xiaodi.wu at gmail.com
Wed Oct 12 10:55:47 CDT 2016


On Wed, Oct 12, 2016 at 10:31 AM, Nate Cook via swift-evolution <
swift-evolution at swift.org> wrote:

> Thanks for your feedback! Response below.
>
> On Oct 12, 2016, at 5:40 AM, Daniel Vollmer via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Hi,
>
> 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).
>
> On 11 Oct 2016, at 23:28, Nate Cook via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> [snip]
>
> On a shallow read I like presented approach, except for
>
> Both the keys and values collections share the same index type as
> Dictionary. This allows the above sample to be rewritten as:
>
> // Using `dict.keys.index(of:)`
> if let i = dict.keys.index(of: "one") {
>    dict.values[i].append(1)
> } else {
>    dict["one"] = [1]
> }
>
>
> 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`?
>
> ```
> // Using `dict.keys.index(of:)`
> if let i = dict.keys.index(of: "one") {
>    dict[i].append(1)
> } else {
>    dict["one"] = [1]
> }
> ```
>
>
> 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:
>
> var dict = ["one": [1], "two": [2, 2], "three": [3, 3, 3]]
>
> // Iterating the dictionary itself would be like we now iterate the values
> collection
> for val in dict {
> print(val)
> }
> // Output is just the values (unordered as usual)
> // [1]
> // [3, 3, 3]
> // [2, 2]
>
> // Iterating a new view would act like the dictionary currently does
> for (key, val) in dict.keysAndValues {
> print(key, val)
> }
> // "one", [1]
> // "three", [3, 3, 3]
> // "two", [2, 2]
>
>
> Any sequence or collections operations on the dictionary itself would only
> interact with values:
>
> print(dict.first)
> // Optional([1])
> print(dict.first(where: { $0.count > 2 }))
> // Optional([3, 3, 3])
>
>
> 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 *all* 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.
>
> 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?
>

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:

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.

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.
>
>
> 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.
>
> Thanks again,
> Nate
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161012/1654ae84/attachment.html>


More information about the swift-evolution mailing list