I agree that any Collection is not the best example for existential extensions. Equatable or Hashable is more useful to think about.
So, let's hypothetically consider the reasons for existential extensions.
Currently, AnyHashable fills the job as a type eraser of a value that's known to be Hashable. Not only this, but AnyHashable is, itself, a Hashable entity.
The way this has been accomplished from the inception of the language is through a type erasing wrapper. Something that looks like this:
Additionally, AnyHashable.init is rarely called because Swift implicitly converts Hashable values into AnyHashable containers.
So, seemingly, type-erasers should ideally follow these two patterns:
A type-eraser should conform to its erased type's protocol (aka self-conformance).
A type-eraser should allow implicit conversion from its erased type to itself.
With Swift 5.7, the existence of any Hashable seemingly supersedes AnyHashable seeing that:
An existential can conform to their own protocols (e.g. any Error conforms to protocol Error).
An existential does allow implicit conversion from its conforming type to itself.
That's why I believe there's value in keeping the AnyXYZ form as a way to indicate self-conformance. The only difference is that the required syntax would be elegantly reduced to just this:
Itâs already confusing enough. Iâve already learned enough things by doing what I think is right and having the compiler tell me it was wrong and how to fix it to agree with the âlet the compiler guessâ plan.
"guess" sounds like "heuristic" above. Again, I haven't been able to imagine an example with any ambiguity. I'm sure you're both thinking of something I'm notâplease demonstrate!
I definitely do not have an example. Until Becca explained it with chickens and boxes at WWDC I didnât even really understand the concepts. I just put some when SwiftUI told me to and avoided using existentials.
My preference would be to keep some P so that bare P is unambiguously for use in conformance clauses, but I may be swayed to prefer eliding (and simultaneously with anyâs introduction) if Ben is right about the change from default-existential to default-opaque in existing code being nearly seamless.
No, if we were to elide some in Swift 6, you would still be able to use a bare protocol name as a conformance constraint without any special new syntax. It's no different than what happens today when you write a bare P in a type context to implicitly mean any P, but <T: P> and <T> where T: P still does the right thing. Type resolution knows whether it's in type context or conformance constraint context, and can resolve to either a bare protocol or an existential/opaque type accordingly.
Personally I would like to stick to explicit some and any. It seems to me that we would take a step back if we would allow 3 possible declarations where two of them would mean the same but even worse after Swift 6 opposite to current status quo.
In the context of a function or type definition, the last bullet point could only be used as a constraint, that is, after a colon. Another use of the "plain Foo" would be in the protocol definition itself, that it, protocol Foo, and in extensions to it, that is, extension Foo: in any other case you would either use any for declaring an existential (that is, var items: [any Item] = []) or a concrete generic type with some.
I must say I think this is a terrible idea, and very hard to motivate.
We just added any to make it clear that P means different things in where X: P and let x: P = X(). We added three letters but gained a lot of clarity. We also gained a nice parallellism between some P and any P. It's easy to see, easy to use, easy to explain.
Very good, three extra letters are a small price to pay. But now it is suggested that we should remove exactly the same amount of clarity, just to save four letters, that seems very ill advised.
Swift explicitly has a policy of not sacrificing clarity for brevity, isn't that exactly what this does? The only gain is four fewer letters.
The fact that this will make some existing code that implicitly uses any suddenly implicitly use some doesn't seem like a good argument. To me it seems more like a counter argument.
Isn't this exactly the situation we wanted to get away from, where the same syntax is used for two different things? If that was a good argument for introducing any, it's a good argument for not eliding some.
There are only two concepts here - placeholders and existentials. And the former should be used vastly more frequently than the latter. It makes entire sense to me to make the common case bare and the rarer case explicit.
Iâm also not entirely convinced that allowing time with the âsomeâ keyword will serve the programmer education goal in a meaningful way. It seems more likely to me that programmers will sprinkle âsomeâ in their code to get it to compile without seeking or needing much in the way of a deeper understanding of the difference between placeholders and existentials.
My inclination would be that if âbare protocol = placeholderâ is the end goal - which it should be - we just rip off the bandaid and deal with transition confusion now.
No there are three concepts: placeholder, existential and conformance. The idea here is to start spelling the first and last of these in the same way. Up until now the last two were spelled the same, but this was deemed confusing.
In my mental concept map conformance and placeholder are deeply conceptually related. A conformance is describing the properties of the type you youâre defining. A placeholder is describing the properties of the type in a given position.
Conformance is saying âthis type is a member of this protocolâ.
Placeholders are saying âthis parameter is a member of this protocolâ.
Well, conformance and placeholders are dealing with the same situation, a type that conforms to a protocol. But they are used for saying different things about that situation. I mean we care enough about the difference to have a specific notation for "X conforms to P", namely the ":". We could just say `X == some P".