We’re in the middle of Apple’s annual product upgrade cycle and this article is the first in a series of tutorials meant to highlight the most important new features of Swift 4.2. Instead of trying to cover all of the 4.2 features/improvements in one very long article, I’m going go talk about each aspect of the new 4.2 version, one or two features at a time. (If you’re interested in more details as to why I’m focused on 4.2, see section “Swift version methodology” below.) Today, I’ll cover the allSatisfy(_:)
instance method (see also here) of the Sequence
protocol (see also here), of course intimately related to the Collection
protocol (see also here).
Evaluating sequential collections with allSatisfy
In its documentation on the “Sequence and Collection Protocols,” Apple defines the Sequence
protocol as a “type that provides sequential, iterated access to its elements” and defines the Collection
protocol as a “sequence whose elements can be traversed multiple times, nondestructively, and accessed by an indexed subscript.” Previous to Swift 4.2, if we wanted to evaluate — find element(s) in — a sequential collection, we mainly relied on the contains(_:)
and contains(where:)
instance methods of the Sequence
protocol. As you can see in the following examples, these methods tended to be counterintuitive, i.e., less readable. Swift 4.2 added allSatisfy(_:)
to, in my humble opinion, give us a self-evident, readable, and maintainable option. Code should read like English as much as possible — and express logic affirmatively instead of by negation. It’s just is easier on the eyes and brain. So allSatisfy(_:)
“Returns a Boolean value indicating whether every element of a sequence satisfies a given predicate,” where the predicate is a “closure that takes an element of the sequence as its argument and returns a Boolean value that indicates whether the passed element satisfies a condition.”
Here’s an example determining if all numbers in a range are less than 1000, with Swift 4.0 and then using Swift 4.2:
1 2 3 4 5 6 7 8 9 |
let numbersSmallerThanThousands = 0...999 // Evaluate with Swift 4.0. let oldAreSmallerThanThousand = !numbersSmallerThanThousands.contains(where: { $0 >= 1000 }) oldAreSmallerThanThousand // true // Evaluate with Swift 4.2. let areSmallerThanThousand = numbersSmallerThanThousands.allSatisfy{ $0 < 1000 } areSmallerThanThousand // true |
Here’s an example determining if a student passed all classes in her/his last semester, where passing means he/she earned a grade of 2.0 or above in all classes, with 4.0 being the highest grade possible down to 1.0 which means failure, using Swift 4.0 and then using Swift 4.2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
enum Subjects: String { case history case literature case math case science } let semesterGrades = [ Subjects.history: 4.0, Subjects.literature: 3.0, Subjects.math: 4.0, Subjects.science: 3.0 ] // Evaluate with Swift 4.0. let oldStudentPassedSemester = !semesterGrades.contains{ $0.value < 2.0 } oldStudentPassedSemester // true // Evaluate with Swift 4.2. let studentPassedSemester = semesterGrades.allSatisfy{ $0.value >= 2.0 } studentPassedSemester // true |
Swift version methodology
Swift 4.2 is supposedly a step in the direction of the “stabilization” of the language culminating in Swift 5.0 next year. A laudable goal of the move to 5.0 will be binary compatibility between Swift binaries (apps, frameworks…) built in different and most likely later versions of the Swift compiler. We’ll see… Here, we’ll be talking about incremental changes made since the last major Swift language version 4.0, released on September 19, 2017, a significant upgrade from version 3.0. Since Swift 4.1 came out on March 29, 2018, was only available for Xcode 9, and many developers have been exposed to its features, we’ll focus herein on Swift 4.2, the absolute latest version of the language. Yes, Swift 4.2 is available for Xcode 9.4, but that’s just a flash in the pan and this latest version is aimed at OS X 10.14, iOS 12, and Xcode 10, all still in beta, but which will be available for production before you can say “Swift.”