What's New in Swift 4.1


This post is a free translation of the article What's new in Swift 4.1 by Paul Hudson


Swift 4.1 is the first minor release of Swift 4, which brought some useful features with it, such as the automatic use of Equatable and Hashable, conditional matches, etc.


Be sure to install at least Xcode 9.3 , then create a new playground. Let's look at the new features of this version ...


Equatable and Hashable


The protocol Equatable allows you to compare one entity with another. When we speak 5 == 5 , Swift understands what this means because it Int conforms to the protocol Equatable , and therefore it implements a function that describes what " == " Equatable means == for entities of the type Int .

Implementation Equatable in your own types (structures, enumerations) allows you to work with them as well as with strings, arrays, numbers, etc. And it will be good if your structures conform to the protocol Equatable in order to better conform to the general concept of types that are passed by value.


However, the implementation Equatable may not be too elegant. For example, we have such a structure:


struct Person {
    var firstName: String
    var middleName: String
    var age: Int
    var city: String
}

And if you have two type entities Person and you want to compare them, you need to compare all four properties, like this:


struct Person: Equatable {
    var firstName: String
    var lastName: String
    var age: Int
    var city: String

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.firstName == rhs.firstName && lhs.lastName == rhs.lastName && lhs.age == rhs.age && lhs.city == rhs.city
    }
}

It's hard to even read , not to write .


Fortunately, in Swift 4.1 it is possible to automatically match for Equatable , the method == will be generated automatically and will compare all the properties of the first entity with all the properties of the second, as described above. All you have to do is add Equatable to your type, and Swift will do the rest.


Naturally, you can implement your own version of the method == . For example, if your type has a property id that uniquely identifies an entity, you could write == to compare only this property, instead of having Swift do the extra work.


Similarly Equatable , in Swift 4.1, support was also introduced Hashable . Now hashValue can be generated automatically to match this protocol. Hashable usually annoying, because you need to return a unique (more or less unique) hash for each entity. This is important because it allows you to use your entities as keys for dictionaries, or allows you to store entities in sets.


Previously, you had to write something like this:


var hashValue: Int {
    return firstName.hashValue ^ lastName.hashValue &* 16777619
}

Given this, you are now unlikely to need to write your implementation hashValue in Swift 4.1, but if you still need it you can do it (similarly == to Equatable ).


Note: Add these protocols to your types as needed, and do not forget that all fields of your types must also correspond to them.


More information can be found here: Swift Evolution proposal SE-0185 .


Conditional Compliance


The Swift Evolution proposal SE-0143 proposed conditional matches, and they are now in Swift 4.1. This is a powerful feature that will benefit many. Things that have not worked before will now work with her. For example, in Swift 4.0 such code will not compile:


var left: [String?] = ["Andrew", "Lizzie", "Sophie"]
var right: [String?] = ["Charlotte", "Paul", "John"]
left == right

All because String and [String] - are consistent Equatable , but [String?] - not. Conditional matching means that the type will conform to the protocol as long as a certain condition is satisfied. This means that if the elements of the array match Equatable , the entire array matches Equatable .


Conditional matching extends to the protocol Codable , and this will make some things more secure. Take a look at this code:


struct Person {
    var name = "Taylor"
}

var people = [Person()]
var encoder = JSONEncoder()
try encoder.encode(people)

We have an array of one type element Person , and we are trying to convert this array to JSON. Such code compiles quietly in Swift 4.0, but in runtime you get an error because it Person does not comply with the protocol Codable . Swift 4.1 solves this problem: Optional , Array , Dictionary and Set is now consistent with the Protocol Codable only if their content matches the protocol, so the Swift 4.1 this code simply will not compile.


Conditional matching is one of the features that will make life easier for most people, even those who do not write a lot of code.


flatMap is now (almost) compactMap


flatMap() useful for many things in Swift 4.0, but its main ability is to transform entities into collections, simultaneously removing nil from the result.


The Swift Evolution proposal SE-0187 suggested changing this, and in Swift 4.1 it was flatMap() renamed compactMap() to more clearly convey its meaning.


For example:


let array = ["1", "2", "Fish"]
let numbers = array.compactMap { Int($0) }

This will create an array with elements of the type Int that will contain the numbers 1 and 2, because "Fish" Int will return nil and will be ignored Int when converted to nil .


Waiting for Swift 5.0


Implementation of conditional compliance contributes to stability, and automatic support Equatable and Hashable will definitely make life easier for developers.


Other offers are either under review or under development, including: SE-0192: Non-Exhaustive Enums , SE-0194: Derived Collection of Enum Cases and SE-0195: Dynamic Member Lookup .


It is equally important that this year Apple, we hope, will release ABI stabilization for Swift, and it will be great . We are waiting, sir.