I'm confused about when to use any when I have a variable that can contain instances of multiple types, as long as they conform to a specific protocol. (I believe this is called an existential type, but not sure).
protocol Quantifiable {
func cost() -> Double
}
var q: any Quantifiable = 1 // okay, Int conforms to Quantifiable
print(q.cost()) // can use the members of the Quantifiable protocol
q = "Hello"
However, this code also works, and seems to be functionally equivalent:
var q: Quantifiable = 1 // okay, Int conforms to Quantifiable
print(q.cost()) // can use the members of the Quantifiable protocol
q = "Hello"
print(q.cost()) // can use the members of the Quantifiable protocol
I understand that adding any was added in Swift 5.7, but I've tested using Swift 5.10 and don't get a compiler warning/error. Code just runs.
In practice, I always use the var foo: MyProtocol = ... and that seems to work fine.
So, when would you need to add the any keyword?
Thanks in advance!
KR Maarten
* I enjoy this series a lot, even though I'm anything but a C++ Practitioner.
Before Swift 5.7, the spelling for any P was just P. Note you could only reference protocols without associated types or Self requirements like this until Swift 5.7 lifted this. To preserve source compatibility with these simpler protocols in older code, P is still accepted in the Swift 5 language version but requires any P for protocols like Equatable, etc.. any P will be required for all protocols with the Swift 6 language version mode iirc.
The Language Steering Group has decided that one previously-accepted upcoming feature, ExistentialAny, will not be enabled by default in Swift 6. SE-0335: Introduce existential any introduces the any keyword to identify existential types. The proposal also specifies that "bare" protocol names will no longer be permitted as types---they must either use any or some, as appropriate---under the upcoming feature flag ExistentialAny. Given the concerns about migration to consistent use of existential any in the language, and the expectation that additional language improvements will be coming that might affect the end result of that migration, the Language Steering Group is deferring the source-incompatible changes in SE-0335 to a future language revision.
I would still suggest getting into the habit of writing any P everywhere because it's the better syntax IMO:
One consistent spelling for all existentials
Using different spellings for when a protocol is used as a constraint (no any) vs. when it's used as an existential is a good thing
Nice congruence between the any P and some P spellings, which can be used in similar places (though note that there have been discussions to make the plain P spelling actually mean some P in a future language version because some P should generally be preferred unless you explicitly need any P)
I remember my initial reluctance for prefixing all protocols with any, particularly because of any Error which is ubiquitous, and the vexing optional (any P)? that requires parenthesis (the plain any P? would be just as good). But I came up with the same conclusions as @ole. I'll add two cents:
Using any is a way to bring the topic of type erasure to the consciousness. It's not always necessary, but well at some point a Swift developer has to understand this. (Unrelated note: @Douglas_Gregor was able to avoid the word "existential" in his blog post, and this is remarkable.)
When I read func f(x: any P), I want to turn it into func f(x: some P). On the other side, func f(x: P) does not trigger me at all. To make my point more clear: not all protocols are named in a way that makes it obvious that they are protocols. For them, the shorthand notation P does not make it obvious that some P could avoid an unnecessary boxing and allow specialization in performance critical paths. In func draw(shape: Shape), what says that Shape is a protocol instead of, say, an enum?