I am trying to understand the exact limits on enums with generic associated values in Swift.
You might think that they are supported, since Optional
is such a type. Here is the code defining Optional
in the Swift standard library:
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
// ...
}
It seems like the case member Some
has an associated value of variable type T
, right?
However, it is mentioned in the book Functional Programming in Swift (p 87), that such types are not supported:
We would like to define a new enumeration that is generic in the result associated with Success:
enum Result<T> { case Success(T) case Failure(NSError) }Unfortunately, generic associated values are not supported by the current Swift compiler.
And indeed, if you type that snippet into the compiler, you get an error (error: unimplemented IR generation feature non-fixed multi-payload enum layout
).
So what is going on here? Is it just that it is not supported in general, but is supported for Optional
as a special case? Is there any way to see how Optional receives this special support? Or if other standard library types also get special support?
In Swift 2 (as part of Xcode 7), there is no limitation on associated values. So, feel free to dance to beats like this:
enum YouCanGoWith<T, U> {
case This(T)
case That(U)
case Us
}
Now, if you're looking for a Success-or-Error kind of enum, you might want to stop and think about why... because Swift 2 also brings a new error handling model. So you don't need such a type as the return value of your functions — you can just declare it like so:
func walkWith(rhythm: Bool) throws -> Place { /* ... */ }
...and if your function succeeds, the caller always gets a (non-optional) Place
for walken to. And — separately from using the result — the caller decides how to handle, swallow, or propagate the error.
For details on that, see Error Handling in The Swift Programming Language. Look closely — the syntax looks a bit like the exception model you see in some other languages, but Swift errors are an entirely different kind of animal.
(Of course, the throws
model is specific to synchronous calls. If instead you're declaring callbacks for asynchronous processes, where the callback closure receives either the result of successful asynchronous work or an error — a Success-or-Error type is still entirely appropriate.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With