Is “some” keyword really necessary?

Hello everyone,

I would like to ask is the introduction of “some” a well-designed feature?

I could only find one case, when “some” really makes type declaration shorter (e. g. some Collection), while in other cases it makes it 5 characters longer.

One more thing about it — Xcode fails building with error, asking you to use protocol type with “any” (and doesn’t even mention “some” that is actually suitable for lots of cases) which performance is not great, thats why we are asked to use it when really necessary during WWDC.

I would consider a good idea an “implicit “some””. So the type declaration would look like in previous Swift versions and won’t make programmers add 5 more characters. And as Swift wants to be friendly with beginners — this would allow to avoid unnecessary concepts at start.

This has been discussed recently here!

1 Like

Here as well!

1 Like

It would look like in previous Swift versions, but the meaning would be different.

I’m curious, how could an expression ever be shorter with explicit some than without it, you said you found an example of that with Collection?

@Jumhyn @Dan_Stenmark thank you :slight_smile:

Yes, consider following:

  • func doSomething(with collection: some Collection)
  • func doSomething<T: Collection>(with collection: T) where T.Element == Int

Why couldn’t you just remove the some there?

I’ll also note that “shorter” isn’t necessarily the thing to optimize for. any types were shorter before they required any, but having any makes them clearer when some is also available…and it meant people wouldn’t “default to” any because they had to choose between any and some.

I’m personally still chewing on the idea of removing some, but I’ll wait until there’s a formal review to put my thoughts in order.

15 Likes

There’s be no way to maintain source compatibility otherwise. If a protocol P does not have associated types, then P by itself is the existential type (what we now prefer to spell as any P, but that syntax was only introduced in Swift 5.6). You’re right that perhaps the fixit for a protocol with associated types, like Collection, should offer to insert either ‘any’ or ‘some’.

You’re well aware of this, but I’ll also add that what it comes down to is that protocols are not types, they’re requirements imposed on types - a form of contract. It seems a lot of the confusion appears when folks coming from languages whose protocols are less expressive than Swift’s assume that protocols are types. If you don’t have static methods, initializers, Self or associated types, there is indeed a one-to-one correspondence between protocols and type-erased containers (like interfaces in Java) but once you have those new kinds of protocol requirements, it gets tricky. It’s one of those situations where making a construct more general makes things less orthogonal in a sense. I personally feel it’s still the right tradeoff, but it does make the language harder to learn (or perhaps just makes habits from other languages harder to unlearn).

14 Likes

Is this distinction something that most people should know when using the term ‘type’ in relatively casual Swift discussions? Just curious… it feels like the language needs a simple term to refer to the stuff that comes after a colon in a variable declaration, etc. Maybe it’s a ‘grilled cheese’ vs. ‘melt’ situation and I’ve been wrong this whole time.

Because Collection protocol has associated types, so you have to tell the compiler you are using the certain implementation of this protocol. Saying certain I mean that you have the same type of implementation which in it's turn has the same associated types. Maybe it is doesn't add clarity for a human in my examples, so take a look at these examples, which will help you see the difference.

P.S. You can take a look at WWDC sessions on this topic: What's new in Swift 5.7, Embrace Swift generics, Design protocol interfaces in Swift

I know it’s not possible today, but you’re proposing dropping the some. It sounded like you said that dropping it saves letters, except in the collection example. But maybe I misunderstood.

Either way I definitely don’t think we should allow it to be elided.

Existentials behave as types most of the time, but “some T” very often doesn’t.

Thinking of the topic of discussion I have a strong feeling that "any" and "some" appeared as "crutches" (not sure if this saying exists in English, but I think you get it) for associated types. And if it was possible the core team wouldn't increase the "trickiness" of this aspect, allowing us to use just protocol name (without any additional clarification) for all purposes.

1 Like

I meant that the only application of "some" I found is replacing non-necessary generic-type constraints

Could you explain in more detail?

For me it looks like it is fully compatible in the sense of old code working in new Swift:

protocol Existential {}

<5.6:
func takeSomeExistential(_ e: 'implicit any' Existential)

5.8+:
func takeSomeExistential(_ e: 'implicit some' Existential)

And as I understand this change will only will increase the performance? Or I don't see something? I guess you mean the case when in <5.6 example I could return different implementations of Existential :frowning:

Consider the difference between these two declarations:

func foo(_: [any Equatable])
func foo(_: [some Equatable])

Good example. However, it seems that the question was about another sort of cases, when you don't need to set constraints on the used type. It is a more common scenario, in my opinion, because you much more often use protocols without Self or associated types (and without generics, too). What is the difference in the following example? What is the profit of using some instead of any?

protocol Dependency1 {}
protocol Dependency2 {}

func foo(_: any Dependency1, _: any Dependency2)
func foo(_: some Dependency1, _: some Dependency2)

Even here, there is a distinction between

func foo(_: [some Dependency1])

and

func foo(_: [any Dependency1])
1 Like