Generic Swift 4 enum with Void associated type
In Swift 3 you can omit the associated value of type Void
:
let res: Result<Void> = .success()
In Swift 4 you have to pass an associated value of type Void
:
let res: Result<Void> = .success(())
// Or just:
let res = Result.success(())
In Swift 4, an enum case with a Void
associated value is no longer equivalent to a an enum case with an empty list of associated values.
I believe this is, as Martin says, a result of SE-0029 where you can no longer pass a tuple of arguments to a function and have them "splat" across the parameters (although the proposal was marked implemented in Swift 3, I believe this particular case was picked up later in the implementation of SE-0110 for Swift 4).
As a result, this means you can no longer call a (Void) -> T
as a () -> T
in Swift 4. You now have to pass Void
in explicitly:
let result = Result.success(())
However, I find this pretty ugly, so I usually implement an extension like this:
extension Result where Success == Void {
static var success: Result {
return .success(())
}
}
Which lets you say things like this:
var result = Result.success
result = .success
It's worth noting that this workaround isn't just limited to enum cases, it can be also used with methods in general. For example:
struct Foo<T> {
func bar(_ a: T) {}
}
extension Foo where T == Void {
func bar() { bar(()) }
}
let f = Foo<Void>()
// without extension:
f.bar(())
// with extension:
f.bar()