Understanding the “some” and “any” keywords in Swift 5.7 | by Lee Kah Seng

No more confusion!

Image of confused man.

The some and any keywords are not new in Swift. The some keyword was introduced in Swift 5.1 whereas the any keyword was introduced in Swift 5.6. In Swift 5.7, Apple makes another great improvement on both of these keywords. We can now use both of these keywords in the function’s parameter position!

This improvement not only made the generic functions look a lot cleaner, but also unlocked some exciting new ways to write generic code in Swift. Spoiler alert — we can now say goodbye to the following error message:

protocol can only be used as a generic constraint because it has Self or associated type requirements

Want to know more? Read on!

Before getting into the details, let’s define the protocol we will be using throughout this article.

After that, we will define a Car and a Bus struct that conforms to the Vehicleprotocol and each of them will require different kinds of fuels. Here’s the code:

Notice that the fillGasTank(with:) function’s parameter data type of Car and Bus are not the same, Car requires Gasoline whereas Bus requires Diesel. That is why we need to define an associated type called FuelType in our Vehicleprotocol.

With that out of the way, let’s dive right into the details, shall we?

The some keyword was introduced in Swift 5.1. It is used together with a protocol to create an opaque type that represents something that is conformed to a specific protocol. When used in the function’s parameter position, it means that the function is accepting some concrete type that conforms to a specific protocol.

At this stage, you might be wondering, aren’t we already able to do that?

In fact, you are right. Using the some keyword in the function’s parameter position is exactly the same as using the angle brackets or a trailing where clause at the function signature.

When we use the some keyword on a variable, we are telling the compiler that we are working on a specific concrete type, thus the opaque type’s underlying type must be fixed for the scope of the variable.

One interesting point to be aware of is that assigning a new instance of the same concrete type to the variable is also prohibited by the compiler.

With that in mind, we will have to follow the same rule when using it with an array.

The same goes for the underlying return type of a function.

That’s all for the some keyword. Let’s head over to the any keyword and see what are the differences between them.

The any keyword was introduced in Swift 5.6. It is introduced for the purpose of creating an existential type. In Swift 5.6, the any keyword is not mandatory when creating an existential type, but in Swift 5.7, you will get a compile error if you failed to do so.

As explained by Apple engineers, an existential type is like a box that contains something that conforms to a specific protocol.

Compare the differences between the some and any keyword in Swift
Comparing the some and any keyword

As illustrated in the image above, the main difference between an opaque type and an existential type is the “box.” The “box” enables us to store any concrete type within it as long as the underlying type conforms to the specified protocol, thus allowing us to do something that an opaque type doesn’t allow us to do.

The best part is that, in Swift 5.7, we can now use the any keyword for protocols with associated types! This means that creating a heterogeneous array using a protocol with associated types is no longer a limitation!

How cool is that? 😃

This improvement not only eliminated the “protocol can only be used as a generic constraint because it has Self or associated type requirements” error, but it also makes accomplishing dynamic dispatch on protocol with associated types a lot more straightforward! But that will be an article for another day.

As good as it might seem, the existential type created using the any keyword still has its own limitations. One major limitation is that we cannot use the == operator to compare two instances of the existential type.

If you think about it, this actually kind of makes sense. As mentioned earlier, an existential type can have any concrete type stored in its “box”. To the compiler, an existential type is just a “box”, it has no idea what’s inside the box. Therefore, it is not possible for the compiler to make a comparison when it cannot guarantee that the content of the “box” has the same underlying concrete type.

Another limitation that you should be aware of is that the existential types are less efficient than the opaque types (created using the some keyword). Donny Wals has a great article that discusses this in much detail, I highly recommend you to check it out.

Therefore, even though Apple has made a lot of improvements on the any keyword, it is still recommended to use the some keyword if the opaque types can get the job done.

Improvements to any types in Swift 5.7 = improvements to any types. the any keyword, pass generic arguments, supports self and associated types, primary associated types but you still shouldn’t use them when generics will work
Source: What’s new in Swift

The improvements to the any and some keywords in Swift 5.7 is definitely a welcome one. On one hand, it drastically improved the syntax and readability of our generic code. On the other hand, it opens up new ways for us to write generic code in a much more efficient manner.

I hope this article gives you a good look into the any and some keyword. Feel free to follow me on Twitter so that you won’t miss out on any of my upcoming articles.

Thanks for reading.

News Credit

%d bloggers like this: