How many times have you written this kind of code?
var ratingView: NSView = NSView()
switch rating
{
case .zero:
ratingView = self.ratingBox.zeroDot
case .one:
ratingView = self.ratingBox.oneStar
case .two:
ratingView = self.ratingBox.twoStar
case .three:
ratingView = self.ratingBox.threeStar
case .four:
ratingView = self.ratingBox.fourStar
case .five:
ratingView = self.ratingBox.fiveStar
}
// use ratingView
Having to declare a redundant default value before an exhaustive switch statement that is always going to overwrite it.
So, I thought, why not use an anonymous closure?
let ratingView: NSView =
{
switch rating
{
case .zero:
return self.ratingBox.zeroDot
case .one:
return self.ratingBox.oneStar
case .two:
return self.ratingBox.twoStar
case .three:
return self.ratingBox.threeStar
case .four:
return self.ratingBox.fourStar
case .five:
return self.ratingBox.fiveStar
}
}()
// use ratingView
No more redundancy 
Joe_Groff
(Joe Groff)
2
Note that, even without the closure, the initial value is unnecessary. You can write:
let ratingView: NSView
switch rating
{
case .zero:
ratingView = self.ratingBox.zeroDot
case .one:
ratingView = self.ratingBox.oneStar
case .two:
ratingView = self.ratingBox.twoStar
case .three:
ratingView = self.ratingBox.threeStar
case .four:
ratingView = self.ratingBox.fourStar
case .five:
ratingView = self.ratingBox.fiveStar
}
and the compiler will require that ratingView is bound before reading from it.
8 Likes
Well! You learn something new every day 
Thanks Joe 
1 Like
young
(rtSwift)
5
You can reduce the redundancy even more by using a ResultBuilder:
let ratingView: NSView = eval {
switch rating {
case .zero:
self.ratingBox.zeroDot
case .one:
self.ratingBox.oneStar
case .two:
self.ratingBox.twoStar
case .three:
self.ratingBox.threeStar
case .four:
self.ratingBox.fourStar
case .five:
self.ratingBox.fiveStar
}
}
Doesn't work with dot-syntax unfortunately.
Implementation
func eval<V>(@SingleValueBuilder<V> _ value: () -> V) -> V {
value()
}
@resultBuilder
enum SingleValueBuilder<V> {
static func buildEither(first component: V) -> V {
component
}
static func buildEither(second component: V) -> V {
component
}
static func buildBlock(_ components: V) -> V {
components
}
}
13 Likes