[swift-evolution] [Proposal] Disallow redundant `Any<...>` constructs
matthew at anandabits.com
Fri May 20 20:33:04 CDT 2016
> On May 20, 2016, at 8:16 PM, Brent Royal-Gordon <brent at architechies.com> wrote:
>>> * I think `Any` (without parameters) should be uppercase, and I don't think we should have both `Any` and `any<>` or `any`. Death to the typealias!
>> Why do you think this? `any<>` (or `Any<>`) is replacing `protocol<>`. `protocol` is a keyword, so following the convention you shared it should be all lowercase. Aside from that, it behaves differently than a user-defined type (which would be uppercase).
> What I'm saying is that I strongly prefer this:
> func print(_ values: Any..., separator: String, terminator: String)
> To this:
> func print(_ values: any..., separator: String, terminator: String)
> And that I think it would be confusing and unnecessarily duplicative to have both `Any` and `any<...>` in the language, differing only in capitalization.
If you don’t want the duplication it would be:
func print(_ values: any<>..., separator: String, terminator: String)
The fact that `any` is not a normal type is immediately obvious here. That said, I favor keeping the typealias.
>>> * If type-erasing structs like `AnySequence` are eventually subsumed by this syntax, I would prefer they be called `Any<Sequence>` instead of `any<Sequence>`.
>> Are you arguing this because they are types? They are currently structs. If they were subsumed by this proposal they most definitely would not be structs.
> No—what I'm saying is that, in a choice between `Any<Sequence>` and `any<Sequence>`, I would prefer to use `Any<Sequence>`. The `Any<…>` here is acting like a type (actually, it *is* a type, just a slightly special type) and it should be capitalized like a type.
It can be used as a type in some ways. It can also be used as a generic constraint.
But what happens inside the angle brackets is very different than what happens inside the angle brackets for a generic type. You can most definitely not use it as if it were a generic type. Making that distinction clear is important IMO.
To be honest it won’t bother me much either way. I am arguing mostly out of what I think will cause the least confusion for new users learning the language.
>> If it’s just syntax you’re concerned with, we could add a typealias:
>> typealias AnySequence<T> = any<Sequence where .Iterator.Element == T>
> This is quite the opposite of what I would want—I would much prefer that people use `Any<Sequence>` directly rather than an `AnySequence` typedef. This will help them learn that the feature is there for other situations, like `Any<Equatable>`.
But any<Sequence> is not at all the same as AnySequence. any<Sequence> is a valid existential which can be used as-is. AnySequence is a generic struct that must be bound to a type argument before use. any<Sequence where .Iterator.Element == String> is roughly the same as AnySequence<String>. However, the former is much more verbose (even when you can just say .Element instead of .Iterator.Element), thus the attractiveness of a typealias.
> In general, I believe it's a good idea to expose `Any<…>` directly, rather than hiding it behind a typealias. For the cost of a few extra characters, we expose a lot of power and flexibility directly to the user. For instance, if you see `Any<Collection where .Element == String>`, it's a small step to realize that you could also say `Any<Collection where .Index == Int>`. If you're always using `AnyCollection<String>`, on the other hand, you may never figure that out.
I disagree. Fully written out constrained existentials will quickly become verbose. Typealias is essential to making them comfortable.
>>> * In the `willSet` vs. `willset` thread, I proposed a rule that keywords which fit into a particular syntactic slot should be capitalized like normal members of that slot. For instance, if `dynamicType` is a pseudo-property, it should be capitalized like a property. Since `Any<>` fits in the syntactic slot of a type, it should be capitalized like a type.
>> Any has some overlap with types, but it cannot be used everywhere a type can.
> Are there places where you can use any type *except* an `Any<…>` type? I know there are places where you need to use (for instance) a class or a protocol, but in those cases Swift is rejecting a wide variety of unacceptable types, only one of which is `Any<…>`.
You cannot put any type dependent on generic arguments inside the angle brackets with `any`.
>> This is precisely why it should be lowercase. I don’t believe it falls under that exemption in your proposal. I believe it’s a good exemption when the keyword is indistinguishable to users from a normal member. I don’t believe it’s a good exemption when the behavior is “special” in some way.
> The behavior of a keyword is always "special" in some way; if it weren't, it wouldn't be a keyword. `dynamicType` is special because it's available on all instances, even though `extension Any` is not valid.
`dynamicType` is indistinguishable from a manually implemented property that returns a metatype. The only thing “special” is the implicit implementation for all types. The behavior of the member itself is not “special”.
The fact that `extension any` is not valid adds more weight to the argument that it does not behave like a type or protocol.
> `willSet` is special (compared to accessors from user-provided property behaviors) because you don't need to enable some specific property behavior to get it.
Isn’t that going to change when we have property behaviors? Even if it doesn’t, it could be implemented as a behavior (I believe Joe had an example of this in the proposal).
> And `Any` is special because it's variadic and acts as a subtype of many unrelated types. But it still walks like a type and quacks like a type, and so we should still spell it like a type.
There are similarities but I think the differences are significant enough to warrant exempting `any` from your exemption rule. They are certainly much more significant than in any of these other cases.
> Brent Royal-Gordon
More information about the swift-evolution