Swift 2: “for… in” filtering
While looking through slides for What’s New in Swift again, I’ve decided to instead play around with and write down the new Swift 2 idioms here for easy reference for myself (and hopefully others). This post focusses on the “for… in” filtering:
The Concept
The idea behind “for… in” filtering is that now you can do filters inline vs in your for loop. So instead of this:
let numbers = [1,2,3,4,5,6,7,8,9,10] // BS2 (Before Swift 2) for number in numbers { if number % 2 == 0 { print(number) } }
You can now do this!
let numbers = [1,2,3,4,5,6,7,8,9,10] // Swift 2 for number in numbers where number % 2 == 0 { print(number) }
“for… in” + Pattern Matching
Note that you can use the pattern matching with “if case” in combination with the for…in filtering for some even more advanced filtering! Here is one example:
let taylorSwiftAlbumsWithYear = [ ("Red", 2014), ("1989", 2014), ("Fearless", 2008), ("Speak Now", 2008)] for case let (album, 2014) in taylorSwiftAlbumsWithYear { print("Taylor Swift's album \(album) was released in 2014") } // printed: // Taylor Swift's album Red was released in 2014 // Taylor Swift's album 1989 was released in 2014
Filtering with Enum
Finally, you can filter enum values like this:
enum MyEnum { case MyEnumCase(String) case MyOtherEnumCase(String) } let enumValues = [MyEnum.MyEnumCase("someValue"), MyEnum.MyEnumCase("someOtherValue"), MyEnum.MyOtherEnumCase("NatashaTheRobot was here")] for case let .MyEnumCase(value) in enumValues { print(value) } // someValue // someOtherValue
Note here that the let outside the enum case refers to the value inside 🙁 I hope the Swift team updates this syntax to be what they had in their slides:
// MORE READABLE IMO, BUT DOES NOT WORK for case .MyEnumCase(let value) in enumValues { print(value) }
Filtering Optionals
An implication of filtering of enum values is that you can now filter Optionals:
let numbersWithOptions: [Int?] = [nil, 1,2,4, nil, 6] for case let .Some(number) in numbersWithOptions where number % 2 == 0 { print(number) }
But of course you should use the version using the new shorthand syntax for .Some(let number):
let numbersWithOptions: [Int?] = [nil, 1,2,4, nil, 6] for case let number? in numbersWithOptions where number % 2 == 0 { print(number) } // 2,4,6
If you’re confused by the ? in theAnswer?, see my blog post on the new unwrapping optionals with pattern matching.
This still doesn’t feel natural to me. I’ll have to look back on this blog post a few times as I’m refactoring my code for Swift 2!