I published a "revised" look at this that uses a less controversial example as people were getting stuck on this example being an
Either<T,U>
(enum based) instead of looking at structs vs. tuples.
: .info
I've been playing around with using named tuples instead of structs for pure data types. One such use case was in returning errors from a function.
Let's say we a function foo
and we want to return an Int
or an Error?
. There are lots of ways to model this: structs, enums, tuples, inout parameters, global error state, etc…
Of course, each has their positives and negatives. However, I want to look at what the difference of the struct and the tuple implementation looks like.
The function definition will look like this:
func foo() -> IntOrError {}
The struct would look like this (Error
is my own custom error type, you could use NSError
too):
struct IntOrError {
let value: Int
let error: Error?
}
The tuple would look like this:
typealias IntOrError = (value: Int, error: Error?)
Usage of the two looks exactly the same:
let result = foo()
if let error = result.error {
println("Uh oh! An error occurred")
}
else {
println("The value is: \(result.value)")
}
So should you use tuples? Well, I don't know. =) There are two big disadvantages of the tuple approach:
- No generics support; I cannot create:
typealias ErrorOf<T> = (value: T, error: Error?)
. I consider this a deficiency in the generics system of Swift though. - No ability to add functionality to the type itself; essentially no OOP-style programming. This also extends to specific initializers.
However, the I see some benefits for the tuple approach too:
- Much faster prototyping while maintaining good readability of code
Currently (as of Beta 6), tuples as return types perform much better than structs. This should get better though.Update: I think the root cause of this was due to rdar://18111139: Swift: Optimizer Perf Bug with inline/external class definitions.- "Upgrading" to a full-blown struct requires only updating the definition of your code (beware, this would be a breaking change for code linking your code though).
If all you need is a dumb data type, try out the named tuple!