To keep the discussion grounded in reality, here are two examples off the top of my code base.
Example 1: Preparing for a storyboard segue using switch/case/where
Before:
case let destination as UINavigationController:
guard let destination = destination.topViewController as? HiddenPuzzlesViewController else {
break
}
destination.dataSource = self
destination.delegate = self
After:
case let destination as UINavigationController where let destination = destination.topViewController as? HiddenPuzzlesViewController:
destination.dataSource = self
destination.delegate = self
Example 2: Updating visible cells in a collection view using for/where
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
for cell in collectionView?.visibleCells where let cell = cell as? PuzzleListCell {
cell.setEditing(editing, animated: animated)
}
}
Note that both examples feature shadowing. I would expect it to work like e.g. guard let works inside of a switch/for statement today. Also note that in the second example, the for loop iterates over an optional collection as proposed in the optional iteration thread.
IMO, in both cases, readability is significantly improved.
for cell as? PuzzleListCell in collectionView?.visibleCells {
cell.setEditing(editing, animated: animated)
}
?
Maybe it should be without the question mark, since the following does work today:
func f(_ anys: [Any]) {
for case let e as Int in anys { print(e) }
}
let optInts: [Int?] = [1, 2, nil, 3]
f(optInts as [Any])
// will print
// 1
// 2
// 3
So the last example could perhaps be written like this today:
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if let cells = collectionView?.visibleCells {
for case let cell as PuzzleListCell in cells {
cell.setEditing(editing, animated: animated)
}
}
}
I've written some for...guard loops in the past, and it happens quite a lot that my first thought is using the where clause, which can perform the check, but can't give you the type safety afterwards.
But imho it would be better not to extend the capabilities of where, and bring for more in line with if and while instead by allowing a comma-separated list of conditions:
for user in users, user.hasBirthdayToday, let profilePic = user.profilePic {
addBirthdayCap(to: profilePic)
}
What I like about this approach is that it could be extended:
for let sections = optionalSections, section in sections, row in section {
print(row.title)
}
This would not only allow convenient iteration over optional sequences, but also walking nested structures.
That's a bit of an expansion to the idea of multiple patterns in a for. It's an interesting idea, but I'm not sure how practical it would be given that a lot of times I've used nested loops, I generally want to break the inner iteration at some point. So unless you allow specifying labels to each iterable (which I guess would be possible) that would limit what you could usefully do with this.