100% bikeshed topic: DictionaryLiteral

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

Any further thoughts welcome.

2 Likes

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

Agreed so far, and I'd like to add CollectionOfPairs to the list.

Some more fun facts about this type:
- Besides Dictionary, it's the only other type in the standard library that is expressible by a dictionary literal
- Unlike Dictionary, it *does* maintain the order of its pairs
- Unlike Dictionary (part 2), it *doesn't* require the first element of the pairs to be Hashable

Nate

···

On Jan 8, 2018, at 6:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

Any further thoughts welcome.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

Wow. This is really gross, I didn’t know it existed :-)

Random question for you. DictionaryLiteral has this doc comment:

/// You initialize a `DictionaryLiteral` instance using a Swift dictionary
/// literal. Besides maintaining the order of the original dictionary literal,
/// `DictionaryLiteral` also allows duplicates keys. For example:

why is maintaining duplicate keys a feature?

It also has this one:

/// Some operations that are efficient on a dictionary are slower when using
/// `DictionaryLiteral`. In particular, to find the value matching a key, you
/// must search through every element of the collection. The call to
/// `index(where:)` in the following example must traverse the whole
/// collection to find the element that matches the predicate:

Since it is immutable, why not sort the keys in the initializer, allowing an efficient binary search to look up values?

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

I’m not familiar with this type at all, so I apologize for the dumb question but… why was this added in the first place? If it is the wrong thing, why not just deprecate it in Swift 5 and remove it in a future release? That avoids it being an ABI concern, because we could make it be force inlined into any client code.

Finally, is anyone actually using this type?

-Chris

···

On Jan 8, 2018, at 4:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

Since it is a generic type, could it not be nested inside of the appropriate Dictionary<Key, Value> type? That would make 2 or 3 more reasonable.

Also, what about Dictionary<Key, Value>.KeyValuePairs?

- Karl

···

On 9. Jan 2018, at 01:29, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

Any further thoughts welcome.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I think this type might become more useful if we find a good name for it and better document it. For example, it is a natural fit for parameter list of Chris’ callable type proposal.

Since this type accepts duplicate “keys” and does not provide key-based lookup, the first thing that deserves a rename is “Key” generic parameter. I recommend naming it “Label”.

This type represents how a dictionary literal looks, not what it means. When we consider the look of it, a dictionary literal is an array literal where each element is labeled.

I can’t think of a really good name, but we may be able to find a more accurate and less confusing name.

Some of the more accurate names are:

LabeledElementCollection
LabeledValueCollection
LabeledValueList
LabeledList

By the way, why this type does not conform to any of the collection protocols while duplicating a lot of collection APIs?

···

On Jan 8, 2018, at 4:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

Any further thoughts welcome.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I think the best solution by far would be to provide an `extension Array: ExpressibleByDictionaryLiteral where Element == (Key, Value)` conformance. Besides the name, `DictionaryLiteral` basically has the same semantics as `Array`, but an impoverished subset of its functionality; using `Array` would reduce the standard library's surface area *and* improve the usability of code which currently uses `DictionaryLiteral`.

The problem is that this isn't currently expressible in the type system. If we can, I would actually support including some kind of unprincipled private hack so we could say `where Element: _AnyTupleOfTwo`. It seems like enough of a win, in both surface area and functionality, to justify a little compiler weirdness. (And we don't need to test for `_AnyTupleOfTwo` conformance at runtime, so I don't think it's a problem if `is` and `as?` don't work.)

···

On Jan 8, 2018, at 4:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

--
Brent Royal-Gordon
Architechies

2 Likes

I was around when we were naming this type, and I don't think it is
misnamed. However, I just read the documentation and I don't believe
it explains the intended use of the type, hence we have this
confusion.

The intended use case for DictionaryLiteral is to build DSLs. Swift
provides types in the standard library that are efficient and lossless
representations for all literals, but are also useful as your
workhorse data types: string literal -- String, array literal --
Array, integer literal -- [U]Int64, kinda (there is some
dissatisfaction with integer literals since there is no type to
capture a >64 bit literal, which is useful for defining a bigint
type). But there was no type that could capture a dictionary literal
in a lossless form, maintaining the order of items, not imposing
dictionary limitations like uniqueness or hashability of keys.

Therefore, we added DictionaryLiteral. Yes, it did land together with
Mirrors in commit 50c6e936d4b94b9736a8d060ddf052ef1ba9c74d, but the
intent was that it is a generally useful library component unrelated
to Mirrors, and therefore we did not add any Mirror-related words to
the name (we couldn't nest it in Mirror because nested generics didn't
work at the time). In fact you can see the comment in Mirrors.swift
that has been preserved to this date:

// This component could stand alone, but is used in Mirror's public interface.

Mirrors just *use* DictionaryLiteral to build a small DSL in the
initializer of Mirror, so that callers could call that initializer
representing Mirror's children with a nice intuitive syntax using a
dictionary literal.

Therefore, based on this intended use, I think that trying to hint
that this type is a general *collection* of any kind is a disservice
for users -- DictionaryLiteral wasn't intended to be a collection, and
it does not have performance characteristics anyone would reasonably
expect from it. We could add more words to the name to paint it more
an "advanced tool shade", for example, CapturedDictionaryLiteral,
DictionaryLiteralSyntax or something along those lines, but I feel
like the impact of that to fix the confusion would be minimal.

Instead, I think the right way to fix the confusion is to adjust the
documentation to not claim that it is first and foremost a collection,
because currently documentation is only technically correct, but does
not explain the intended use of the type at all.

Dmitri

···

On Mon, Jan 8, 2018 at 4:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

2 Likes

It’s really not related to the Dictionary type. This isn’t part of Dictionary’s implementation leaking out, like DictionaryIndex or DictionaryIterator were. It’s a separate independently (marginally-) useful type.

···

On Jan 8, 2018, at 5:08 PM, Karl Wagner <razielim@gmail.com> wrote:

On 9. Jan 2018, at 01:29, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

Any further thoughts welcome.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Since it is a generic type, could it not be nested inside of the appropriate Dictionary<Key, Value> type? That would make 2 or 3 more reasonable.

Also, what about Dictionary<Key, Value>.KeyValuePairs?

- Karl

1 Like

While there’s nothing specifically to do with a dictionary, it is a literal
in at least one essential respect. Like other literals, it doesn’t have a
type, but values that are expressed by them do acquire a type given the
context.

Yes, it's not a dictionary, but neither is an integer literal an integer
(or even necessarily an integer you can create from such a literal: it can
be a floating-point value you create from that literal), etc. Would
"ordered collection of key-value pairs" be more "correct"? By the same
token, we ought to be renaming integer literals "ordered collection of
digits without interposed decimal point."

But essentially every user will have encountered this spelling in the
context of dictionaries: in other words, its name has a good basis in
reality because it is the (only) literal spelling that can be used to
create a dictionary, and when you say "hey, that spelling you use for a
literal to instantiate a dictionary in Swift," everyone will know what
you're talking about.

No, I think we ought to do nothing. It's not only "not bad," but as far as
I can tell quite superior to the alternatives in essentially every respect.
In the alternative, maybe "KeyValueLiteral" or something of that sort, but
I still would consider that to be strictly inferior to "DictionaryLiteral".

···

On Mon, Jan 8, 2018 at 20:24 Nate Cook via swift-evolution < swift-evolution@swift.org> wrote:

> On Jan 8, 2018, at 6:29 PM, Ben Cohen via swift-evolution < > swift-evolution@swift.org> wrote:
>
> There exists in the standard library a type `DictionaryLiteral` that
deserves naming re-consideration before we declare ABI Stability, because
it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide
key-based lookup of values) nor a Literal.
>
> Instead, it’s just an immutable collection of key-value pairs you can
create _from_ a literal.
>
> I’m canvassing for opinions on what it ought to be called. Some
suggestions so far:
>
> - `AssociationCollection`: Following the term of art from some other
languages. Slightly obscure-sounding to developers not already familiar.
Also “association” and “associative” are confusingly similar, which brings
back the is-this-a-dictionary problem.
> - `KeyValueCollection`: Problematic because key-value comes up in a
totally different context in Cocoa.
> - `PairCollection`: “Pair” is kinda nondescript.
> - Do nothing. It’s not so bad.

Agreed so far, and I'd like to add CollectionOfPairs to the list.

Some more fun facts about this type:
- Besides Dictionary, it's the only other type in the standard library
that is expressible by a dictionary literal
- Unlike Dictionary, it *does* maintain the order of its pairs
- Unlike Dictionary (part 2), it *doesn't* require the first element of
the pairs to be Hashable

Nate

> The old name can live on indefinitely via a typealias (which has no ABI
consequences, so could be retired at a later date once everyone has had
plenty of time to address the deprecation warnings). Removing it as not
carrying its weight (and instead using `[(Key,Value)]`, which is basically
what it’s a wrapper for) is probably off the table for source stability
reasons.
>
> Any further thoughts welcome.
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Nate

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

Wow. This is really gross, I didn’t know it existed :-)

Random question for you. DictionaryLiteral has this doc comment:

/// You initialize a `DictionaryLiteral` instance using a Swift dictionary
/// literal. Besides maintaining the order of the original dictionary literal,
/// `DictionaryLiteral` also allows duplicates keys. For example:

why is maintaining duplicate keys a feature?

It also has this one:

/// Some operations that are efficient on a dictionary are slower when using
/// `DictionaryLiteral`. In particular, to find the value matching a key, you
/// must search through every element of the collection. The call to
/// `index(where:)` in the following example must traverse the whole
/// collection to find the element that matches the predicate:

Since it is immutable, why not sort the keys in the initializer, allowing an efficient binary search to look up values?

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

I’m not familiar with this type at all, so I apologize for the dumb question but… why was this added in the first place? If it is the wrong thing, why not just deprecate it in Swift 5 and remove it in a future release? That avoids it being an ABI concern, because we could make it be force inlined into any client code.

According to now-gone doc comments, it's intended to be used when providing the children for a custom mirror (that's the only API I know of that uses the type). The order of elements there is important, but given how scarcely used the type is, an array of tuples might be a reasonable (though source-breaking) substitute.

Finally, is anyone actually using this type?

In the standard library, we have this Mirror initializer: https://developer.apple.com/documentation/swift/mirror/1540408-init\. If anyone is customizing their type's mirror, it's a good bet that they're calling that init and passing a literal that would break if the argument changed to an array. The translation should be mechanical, so maybe it could be a migrator fix? (I don't know enough about how that works to know.)

···

On Jan 9, 2018, at 12:12 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 8, 2018, at 4:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.

Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.

Wow. This is really gross, I didn’t know it existed :-)

Random question for you. DictionaryLiteral has this doc comment:

/// You initialize a `DictionaryLiteral` instance using a Swift dictionary
/// literal. Besides maintaining the order of the original dictionary literal,
/// `DictionaryLiteral` also allows duplicates keys. For example:

why is maintaining duplicate keys a feature?

Allowing duplicate keys can be useful depending on the use case. Though you could argue they shouldn’t be called keys then…

This type can be described as “just an ordered immutable list of pairs that you can declare using the `[:]` syntax because that looks nicer than `[(,)]`” . Allowing duplicate keys, and preserving declaration order, is just what it does.

One thought I had was we could replace it with conditional conformance by making `Array: ExpressibleByDictionaryLiteral where Element = (Key,Value)`. But we can’t do that quite yet, because I think it needs [parameterized extensions](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#parameterized-extensions\). Also that might be confusing too ("huh, I can create an array from a dictionary literal???”).

It also has this one:

/// Some operations that are efficient on a dictionary are slower when using
/// `DictionaryLiteral`. In particular, to find the value matching a key, you
/// must search through every element of the collection. The call to
/// `index(where:)` in the following example must traverse the whole
/// collection to find the element that matches the predicate:

Since it is immutable, why not sort the keys in the initializer, allowing an efficient binary search to look up values?

Because it’s currently in user-declared order, like an array. I don’t think we could change that without breaking any code that uses it for what it does today. Here’s an example in the wild that is reliant on preserving order:
https://github.com/apple/swift/blob/master/benchmark/single-source/RomanNumbers.swift#L28\.

We will hopefully add a value-type sorted dictionary too, at some point, which would cover the sorted literal use case.

I’m canvassing for opinions on what it ought to be called. Some suggestions so far:

- `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
- `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
- `PairCollection`: “Pair” is kinda nondescript.
- Do nothing. It’s not so bad.

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

I’m not familiar with this type at all, so I apologize for the dumb question but… why was this added in the first place? If it is the wrong thing, why not just deprecate it in Swift 5 and remove it in a future release?

Given it’s going to be in the ABI regardless, and has at least some marginal utility, if we can find a more sensible name for it is there any strong motivation to deprecate it?

That avoids it being an ABI concern, because we could make it be force inlined into any client code.

"we could make it be force inlined into any client code” isn’t a feature we currently plan on having unfortunately. Also this is a type rather than just a method, so we’d need a feature to always emit the symbol into the client too.

Finally, is anyone actually using this type?

IMO that isn’t a question we should be asking any more except in cases where an existing implementation is causing active harm. Which, confusing name aside, this type isn’t (aside from API sprawl I guess).

···

On Jan 8, 2018, at 10:12 PM, Chris Lattner <clattner@nondot.org> wrote:

On Jan 8, 2018, at 4:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

-Chris

Sorry, I meant to provide an alternative but forgot.

If we can't do this, I think we should call it something like `PairArray` or `KeyValueArray` and augment its API to bring it closer to parity with `Array`. This type really does have the same semantics as `Array`—integer-indexed, order-preserving, random-access, etc.—and I think we should leverage that fact to make its behavior clear.

`PairArray` sort of vaguely suggests that we should have a `public typealias Pair<K, V> = (key: K, value: V)` in the standard library. I think that's actually a good idea, because we can use it to make sure that we use tuple element labels consistently across various APIs.

···

On Jan 9, 2018, at 9:04 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

The problem is that this isn't currently expressible in the type system. If we can, I would actually support including some kind of unprincipled private hack so we could say `where Element: _AnyTupleOfTwo`.

--
Brent Royal-Gordon
Architechies

+1 to “LabeledList”

Nevin

···

On Tue, Jan 9, 2018 at 9:27 PM, Hooman Mehr via swift-evolution < swift-evolution@swift.org> wrote:

I think this type might become more useful if we find a good name for it
and better document it. For example, it is a natural fit for parameter list
of Chris’ callable type proposal.

Since this type accepts duplicate “keys” and does not provide key-based
lookup, the first thing that deserves a rename is “Key” generic parameter.
I recommend naming it “Label”.

This type represents how a dictionary literal *looks*, not what it *means*.
When we consider the look of it, a dictionary literal is an array literal
where each element is labeled.

I can’t think of a really good name, but we may be able to find a more
accurate and less confusing name.

Some of the more accurate names are:

LabeledElementCollection
LabeledValueCollection
LabeledValueList
LabeledList

By the way, why this type does not conform to any of the collection
protocols while duplicating a lot of collection APIs?

While there’s nothing specifically to do with a dictionary, it is a literal in at least one essential respect. Like other literals, it doesn’t have a type, but values that are expressed by them do acquire a type given the context.

This confusion is why we really need to rename this—there are two separate things:

1) Dictionary literals. These are written as comma-separated key-value pairs, with each key-value pair separated by a colon—[a: b, c: d, e: f]. Most users of Swift have probably only ever used these to create instances of the Dictionary type, but any type that conforms to ExpressibleByDictionaryLiteral can be expressed using one. Crucially, like integer literals that can express an `Int` value, a `UInt8` value, or a value of any other integer or floating-point type, dictionary literals have no concrete type until they’re evaluated in context.

2) The `DictionaryLiteral` type. This is a generic type that conforms to ExpressibleByDictionaryLiteral, but is otherwise an unremarkable collection with `(Key, Value)` elements. You can see its declaration here: https://github.com/apple/swift/blob/master/stdlib/public/core/Mirror.swift#L855\. Despite the name, `DictionaryLiteral` is not a literal—it’s a concrete type and can’t be used to express dictionaries or other types that conform to `ExpressibleByDictionaryLiteral`.

It’s #2 that we’re talking about renaming, and while I think both parts of the name (“Dictionary” and “Literal”) are inaccurate, “Literal” is more problematic because of the confusion it causes with lower-case literals.

Nate

···

On Jan 8, 2018, at 9:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Yes, it's not a dictionary, but neither is an integer literal an integer (or even necessarily an integer you can create from such a literal: it can be a floating-point value you create from that literal), etc. Would "ordered collection of key-value pairs" be more "correct"? By the same token, we ought to be renaming integer literals "ordered collection of digits without interposed decimal point."

But essentially every user will have encountered this spelling in the context of dictionaries: in other words, its name has a good basis in reality because it is the (only) literal spelling that can be used to create a dictionary, and when you say "hey, that spelling you use for a literal to instantiate a dictionary in Swift," everyone will know what you're talking about.

No, I think we ought to do nothing. It's not only "not bad," but as far as I can tell quite superior to the alternatives in essentially every respect. In the alternative, maybe "KeyValueLiteral" or something of that sort, but I still would consider that to be strictly inferior to "DictionaryLiteral".

On Mon, Jan 8, 2018 at 20:24 Nate Cook via swift-evolution <swift-evolution@swift.org> wrote:

> On Jan 8, 2018, at 6:29 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:
>
> There exists in the standard library a type `DictionaryLiteral` that deserves naming re-consideration before we declare ABI Stability, because it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide key-based lookup of values) nor a Literal.
>
> Instead, it’s just an immutable collection of key-value pairs you can create _from_ a literal.
>
> I’m canvassing for opinions on what it ought to be called. Some suggestions so far:
>
> - `AssociationCollection`: Following the term of art from some other languages. Slightly obscure-sounding to developers not already familiar. Also “association” and “associative” are confusingly similar, which brings back the is-this-a-dictionary problem.
> - `KeyValueCollection`: Problematic because key-value comes up in a totally different context in Cocoa.
> - `PairCollection`: “Pair” is kinda nondescript.
> - Do nothing. It’s not so bad.

Agreed so far, and I'd like to add CollectionOfPairs to the list.

Some more fun facts about this type:
- Besides Dictionary, it's the only other type in the standard library that is expressible by a dictionary literal
- Unlike Dictionary, it *does* maintain the order of its pairs
- Unlike Dictionary (part 2), it *doesn't* require the first element of the pairs to be Hashable

Nate

> The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.
>
> Any further thoughts welcome.
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Ah I see. What is the plan for Mirrors? I thought they had numerous known deficiencies and should be replaced with a better reflection system. Are they going to make the jump to ABI stability?

-Chris

···

On Jan 8, 2018, at 11:07 PM, Nate Cook <nate@natecook.com> wrote:

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

I’m not familiar with this type at all, so I apologize for the dumb question but… why was this added in the first place? If it is the wrong thing, why not just deprecate it in Swift 5 and remove it in a future release? That avoids it being an ABI concern, because we could make it be force inlined into any client code.

According to now-gone doc comments, it's intended to be used when providing the children for a custom mirror (that's the only API I know of that uses the type). The order of elements there is important, but given how scarcely used the type is, an array of tuples might be a reasonable (though source-breaking) substitute.

Finally, is anyone actually using this type?

In the standard library, we have this Mirror initializer: https://developer.apple.com/documentation/swift/mirror/1540408-init\. If anyone is customizing their type's mirror, it's a good bet that they're calling that init and passing a literal that would break if the argument changed to an array. The translation should be mechanical, so maybe it could be a migrator fix? (I don't know enough about how that works to know.)

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

I’m not familiar with this type at all, so I apologize for the dumb question but… why was this added in the first place? If it is the wrong thing, why not just deprecate it in Swift 5 and remove it in a future release?

Given it’s going to be in the ABI regardless, and has at least some marginal utility, if we can find a more sensible name for it is there any strong motivation to deprecate it?

+1 for renaming it to something that isn’t super confusing, but +100 for removing it outright.

Rationale: if we didn’t have this functionality in the stdlib today, we would not consider adding it. It doesn’t meet the bar we’ve set for what is in the standard library. It only exists there by historical accident. The Mirror API was not carefully considered.

Finally, is anyone actually using this type?

IMO that isn’t a question we should be asking any more except in cases where an existing implementation is causing active harm. Which, confusing name aside, this type isn’t (aside from API sprawl I guess).

It directly impacts code size for applications of swift that use the standard library as a standard library, e.g. a raspberry pi dev situation. It is also bloat, and also takes us down a slippery slope by allowing people to say “if that weird thing is in, why can’t I add my own narrow enhancement?”

More to the point though, this seems like an implementation detail of Mirrors. What is the plan for Mirrors + ABI stability?

-Chris

···

On Jan 9, 2018, at 10:23 AM, Ben Cohen <ben_cohen@apple.com> wrote:

1 Like

Or "KeyValueList", which avoids both "Dictionary" and "Array" words.

-- E

···

On Jan 9, 2018, at 10:22 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:
If we can't do this, I think we should call it something like `PairArray` or `KeyValueArray`

Thank you for the clarification. It occurred to me in the shower that this
might be the case, and that I was entirely mistaken as to what we were
talking about.

Yes, then, I wholeheartedly agree on this point. Out of curiosity, why are
there source stability issues to 'typealias DictionaryLiteral<Key, Value> =
[(Key, Value)]'?

···

On Mon, Jan 8, 2018 at 23:25 Nate Cook <natecook@apple.com> wrote:

On Jan 8, 2018, at 9:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

While there’s nothing specifically to do with a dictionary, it is a
literal in at least one essential respect. Like other literals, it doesn’t
have a type, but values that are expressed by them do acquire a type given
the context.

This confusion is why we really need to rename this—there are two separate
things:

1) *Dictionary literals.* These are written as comma-separated key-value
pairs, with each key-value pair separated by a colon—[a: b, c: d, e: f].
Most users of Swift have probably only ever used these to create instances
of the Dictionary type, but any type that conforms to
ExpressibleByDictionaryLiteral can be expressed using one. Crucially, like
integer literals that can express an `Int` value, a `UInt8` value, or a
value of any other integer or floating-point type, dictionary literals have *no
concrete type* until they’re evaluated in context.

2) *The `DictionaryLiteral` type.* This is a generic type that conforms
to ExpressibleByDictionaryLiteral, but is otherwise an unremarkable
collection with `(Key, Value)` elements. You can see its declaration here:
https://github.com/apple/swift/blob/master/stdlib/public/core/Mirror.swift#L855\.
Despite the name, `DictionaryLiteral` is not a literal—it’s a concrete type
and can’t be used to express dictionaries or other types that conform to
`ExpressibleByDictionaryLiteral`.

It’s #2 that we’re talking about renaming, and while I think both parts of
the name (“Dictionary” and “Literal”) are inaccurate, “Literal” is more
problematic because of the confusion it causes with lower-case literals.

Nate

Yes, it's not a dictionary, but neither is an integer literal an integer
(or even necessarily an integer you can create from such a literal: it can
be a floating-point value you create from that literal), etc. Would
"ordered collection of key-value pairs" be more "correct"? By the same
token, we ought to be renaming integer literals "ordered collection of
digits without interposed decimal point."

But essentially every user will have encountered this spelling in the
context of dictionaries: in other words, its name has a good basis in
reality because it is the (only) literal spelling that can be used to
create a dictionary, and when you say "hey, that spelling you use for a
literal to instantiate a dictionary in Swift," everyone will know what
you're talking about.

No, I think we ought to do nothing. It's not only "not bad," but as far as
I can tell quite superior to the alternatives in essentially every respect.
In the alternative, maybe "KeyValueLiteral" or something of that sort, but
I still would consider that to be strictly inferior to "DictionaryLiteral".

On Mon, Jan 8, 2018 at 20:24 Nate Cook via swift-evolution < > swift-evolution@swift.org> wrote:

> On Jan 8, 2018, at 6:29 PM, Ben Cohen via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> There exists in the standard library a type `DictionaryLiteral` that
deserves naming re-consideration before we declare ABI Stability, because
it’s confusingly misnamed, being neither a Dictionary (it doesn’t provide
key-based lookup of values) nor a Literal.
>
> Instead, it’s just an immutable collection of key-value pairs you can
create _from_ a literal.
>
> I’m canvassing for opinions on what it ought to be called. Some
suggestions so far:
>
> - `AssociationCollection`: Following the term of art from some other
languages. Slightly obscure-sounding to developers not already familiar.
Also “association” and “associative” are confusingly similar, which brings
back the is-this-a-dictionary problem.
> - `KeyValueCollection`: Problematic because key-value comes up in a
totally different context in Cocoa.
> - `PairCollection`: “Pair” is kinda nondescript.
> - Do nothing. It’s not so bad.

Agreed so far, and I'd like to add CollectionOfPairs to the list.

Some more fun facts about this type:
- Besides Dictionary, it's the only other type in the standard library
that is expressible by a dictionary literal
- Unlike Dictionary, it *does* maintain the order of its pairs
- Unlike Dictionary (part 2), it *doesn't* require the first element of
the pairs to be Hashable

Nate

> The old name can live on indefinitely via a typealias (which has no ABI
consequences, so could be retired at a later date once everyone has had
plenty of time to address the deprecation warnings). Removing it as not
carrying its weight (and instead using `[(Key,Value)]`, which is basically
what it’s a wrapper for) is probably off the table for source stability
reasons.
>
> Any further thoughts welcome.
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

The old name can live on indefinitely via a typealias (which has no ABI consequences, so could be retired at a later date once everyone has had plenty of time to address the deprecation warnings). Removing it as not carrying its weight (and instead using `[(Key,Value)]`, which is basically what it’s a wrapper for) is probably off the table for source stability reasons.

I’m not familiar with this type at all, so I apologize for the dumb question but… why was this added in the first place? If it is the wrong thing, why not just deprecate it in Swift 5 and remove it in a future release?

Given it’s going to be in the ABI regardless, and has at least some marginal utility, if we can find a more sensible name for it is there any strong motivation to deprecate it?

+1 for renaming it to something that isn’t super confusing, but +100 for removing it outright.

Rationale: if we didn’t have this functionality in the stdlib today, we would not consider adding it. It doesn’t meet the bar we’ve set for what is in the standard library. It only exists there by historical accident. The Mirror API was not carefully considered.

Personally, I feel like this argument for removal as past its use-by date. It was a good reason for Swift 3, tenuous for 4 and should be ruled out for 5, since the source stability bar has been raised since. Like I said, IMO the criteria should now be “active harm”. I also don’t think searches of GitHub etc are sufficient justification, except when combined with the active-harm argument. I also don’t think the origin story of the type – whether accidental or intentional – is relevant to the decision of what to do with it now. It exists and people can legitimately use it for their own purposes independent of mirrors.

Finally, is anyone actually using this type?

IMO that isn’t a question we should be asking any more except in cases where an existing implementation is causing active harm. Which, confusing name aside, this type isn’t (aside from API sprawl I guess).

It directly impacts code size for applications of swift that use the standard library as a standard library, e.g. a raspberry pi dev situation. It is also bloat, and also takes us down a slippery slope by allowing people to say “if that weird thing is in, why can’t I add my own narrow enhancement?”

The bar for removal and the bar for additions are different. I don’t buy the slippery slope argument, and surely neither would anyone else if it were used as a justification for new frivolous additions, so this seems like a non-issue to me.

More to the point though, this seems like an implementation detail of Mirrors. What is the plan for Mirrors + ABI stability?

Absent a proposal to change them to something better (and I’m not aware of one pending), the plan is they are what they are, at least the public API of Swift.Mirror. I would guess this whole area is a candidate to be overhauled significantly at some point in the post-Swift 5 future with some more fully-fledged reflection system, but there is little chance of this happening before ABI stability, and interim tinkering doesn’t seem worthwhile to me.

···

On Jan 9, 2018, at 11:48 AM, Chris Lattner <clattner@nondot.org> wrote:

On Jan 9, 2018, at 10:23 AM, Ben Cohen <ben_cohen@apple.com> wrote:

-Chris

I’m not arguing that we should have profligate bloat in the Standard library, but I feel that if we are seriously talking about scenarios where we want a super-svelt Standard library for particular use-cases where code size and other factors are a major concern, then I think that discussion goes well beyond just cutting out APIs like Mirrors. Depending on the domain, other parts of the Standard library seem like prime candidates to jettison as they may not carry their weight *in those contexts*, even if those APIs are well-used in others.

In other words, we have various knobs we can pull here in this design space, and the needs of Swift in different domains may be slightly different to be worth exploring different options where appropriate. That’s not to say that the ideas you are putting forth don’t have merit, but I think there is a danger with lumping all of this up with the discussion about ABI stability in Swift 5. More generally, I do think the idea of possibly carving up the Standard Library into layers is a possible useful design idiom when considering Swift being used in different contexts with different requirements/needs/constraints, but an exploration of that idea doesn’t have to be tied to ABI stability.

···

On Jan 9, 2018, at 11:48 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

IMO that isn’t a question we should be asking any more except in cases where an existing implementation is causing active harm. Which, confusing name aside, this type isn’t (aside from API sprawl I guess).

It directly impacts code size for applications of swift that use the standard library as a standard library, e.g. a raspberry pi dev situation.