On the 25th of March Apple announced that the release process for Swift 5.3 has begun, it’s a major change since it will improve the overall language quality and performance, and will make Swift available for multiple platforms as Windows and Linux.
But let’s see in detail what’s new.
Enum Cases as Protocol Witnesses
Currently a class extending a protocol needs to match exactly the protocol’s requirements, for example if we write static requirements within a protocol:
And then we try to conform an enum to our protocol, we’ll face the following error:
With SE-0280 this will no longer cause a compiling error.
Multiple Trailing Closures
Swift 5.3 finally introduced the possibility to use multiple trailing closures.
First of all for those who don’t know what a trailing closure is, it’s a simple syntactic sugar that we can use when we have a closure parameter in a function:
and we can simply call the function as follows:
This is an amazing feature and allows us to write cleaner and easier to read code, however it’s currently limited only to the last parameter of a function as we can see in the following example:
The Proposed Solution
With SE-0279 we will be allowed to insert extra trailing closures, just by adding extra labels, therefore the following code will compile.
A New Float16 Type
This is pretty straight forward, I’ll report the motivation explained by apple:
The last decade has seen a dramatic increase in the use of floating-point types smaller than (32-bit)
Float. The most widely implemented is
Float16, which is used extensively on mobile GPUs for computation, as a pixel format for HDR images, and as a compressed format for weights in ML applications.
Introducing the type to Swift is especially important for interoperability with shader-language programs; users frequently need to set up data structures on the CPU to pass to their GPU programs. Without the type available in Swift, they are forced to use unsafe mechanisms to create these structures.
You can find additional informations on SE-0277.
Multi-Pattern Catch Clauses
Currently swift allows only a single error type for each catch clause, that means that if we define the following enum
Assuming someNetworkCall is a function that throws a NetworkError, and we want to handle both errors, we will need to write two separate catch clauses:
With SE-0276 we will be allowed to handle both errors on a single catch clause, with the following code:
Add Collection Operations on Noncontiguous Elements
Currently we can use Range<Index> to refer to multiple consecutive positions in a Collection, but there’s not a simple way to do this for discontiguous positions, based on some condition.
For example if we have an array of numbers from 0 to 15 and we want to get a sub range of the Array, let’s say with only even numbers, the language doesn’t provide any way to get it, or even to get a sub Array with elements with non contiguous positions, but we can only select a range of contiguous elements:
SE-0270 adds a super useful “RangeSet” Method that will allow us to get a subRange of all the indexes of the elements that satisfy a specific condition, therefore, if we want to get only even numbers from the previous array, the following code will work:
Increase Availability of Implicit self in @escaping Closures when Reference Cycles are Unlikely to Occur
Currently in closures we need to use explicit self even in some cases where reference cycles are unlikely to happen, for example because we already captured self in the current closure:
To make our code compile we need to add explicit self to x in order to reference it.
Another example is with structs, where self is a value type, therefore can’t cause a reference cycle:
With SE-0269 we won’t need to use explicit anymore in the previous cases.
Currently, if we have a property with a “didSet” observer, the getter to get the oldValue is always called, even if observer doesn’t contain any reference to the oldValue in its body, for example the following code
creates 100 copies of the array in the memory to provide the
oldValue, even though they're not used at all, causing performance issues.
With SE-0268 the property getters will be no longer called if they’re not accessed within the didSet resulting in a performance boost
Where Clauses on Contextually Generic Declarations
Currently a where clause on a member declaration can be used only by placing the member inside a specific extension, but this can sound confusing, let’s make an example.
Let’s say we want to extend the Array implementation to sort element of 3 different types, for which we want to define a different sorting logic.
Currently we would need to extend Array 3 times:
With SE-0267 we can implement that logic by simply adding the where clause to the function in a single extension:
Comparable Conformance for Enum Types
Let’s say we want to define an Enum whose cases have an obvious semantic order, for example:
If we try to compare its values we got the following error:
What’s wrong here?
In order to compare two Objects, they need to conform the Comparable protocol:
looking at the warning this will generate a loop, since the < function will be calling itself, therefore we need to compare the rawValues so that we can finally compare our grades
This, is just a simple case, and it adds a lot of boilerplate code.
With SE-0266 this will not be necessary and we don’t need any additional code to compare Enums.
Package Manager Changes
With next Swift release there will be also several major improvements to Swift Package Manager.
Package Manager Resources
Package Manager Conditional Target Dependencies
SE-0273 adds the possibility for package authors to add specific dependencies differentiated by platform.
Package Manager Binary Dependencies
Swift Package Manager currently supports only source packages, SE-0272 adds support for Binary Packages as GoogleAnalytics and many more, and this will make the Swift Package Manager adoption move faster.
Let me know what’s the most useful addition in your opinion and thanks for Reading!