
While not classified as a collection type by Apple, tuples are the new collection-like type found in Swift. Tuples fit in a strange place between structs and arrays, but allow for some rather remarkable flexibility in code — particularly when returning more than one value in a function.
While an array is a collection type containing elements of the same type, A tuple in swift is a collection containing values of varying types. This does not make them a substitute for arrays, but a temporary way of moving several values around at the same time.
Declaring and Accessing Tuples
At its simplest, you declare a tuple like this:
let myPizzaTuple = ("Green Pepper", 18.0)
Alternatively, you can add names for the parts of the tuple.
var myNamedPizzaTuple = (topping:"Mushroom",size:10.0, crust:"Pan")
Getting values from a tuple has a few variations . One is to do the reverse of assigning the tuple, creating two variables with the data of the tuple, like this:
var (topping,size) = myPizzaTuple println("Your pizza is a \(size) inch \(topping)")
You can also use an index starting at 0 to access the elements of the tuple. This index uses dot notation, not a true index like an array.
println("Your pizza is a \(myPizzaTuple.1) inch \(myPizzaTuple.0)")
Outside of the examples here, I personally cannot see a use for this type of access. You can’t enumerate with variables like an array and it makes code difficult to read. My preferred practice is to use the named tuple, like I did with myNamedPizza
:
println("Your pizza is a \(myNamedPizzaTuple.size) inch \(myNamedPizzaTuple.crust) \(myNamedPizzaTuple.topping)")
Consistent with all types in Swift, a constant tuple declared by let
is immutable. A tuple declared by var
allows changing of the values within the tuple, In either case, there is no mechanism to change the number of elements in the tuple.
myNamedPizzaTuple.topping = "Pear Gorgonzola" //works fine myPizzaTuple.0 = "BBQ Chicken" //gives error 'Cannot assign to 0'
You can initialize a variable with a constant tuple, and then change the variable. The tuple is not affected.
topping = "Wasabi Siracha Tuna" println("Toppings are \(topping) pizza and a \(myPizzaTuple.0) pizza")
The code above will print the following:
Toppings are Wasabi Siracha Tuna pizza and a Green Pepper pizza
If the assignment affected the tuple , we would have two mouth burning pizzas, not just one.
The cases above change one element of the tuple’s values. You can change all values in the tuple like this if declared as var
:
myNamedPizzaTuple = (topping:"Pear Gorgonzaola",size:10.0, crust:"Thin")
Using a Tuple
While at first glance tuples look like arrays, they act a lot more like structs. That is how we use them. Let’s look at a parallel example struct. Core graphics has the struct CGPoint
:
struct CGPoint { CGFloat x; CGFloat y; }; typedef struct CGPoint CGPoint;
If we had a case we didn’t need core graphics but needed coordinate data I could declare this
var aPoint = (0.0,0.0) //tuples of Double var anotherPoint = (x:CGFloat(0.0),y:CGFloat(0.0)) //tuples of CGFloat
Line 1 is a simple version which makes the coordinates (x,y) as doubles. We cannot declare type in a tuple, so often we will have to cast or initialize a value in the correct type. In line 2, if we want some compatibility with Core graphics, we initialize (x,y) with CGFloat
and name them.
If I name my tuple, like I did in anotherPoint
I can use tuples like a struct:
anotherPoint.x = 23.4 anotherPoint.y = 16.1
Since we can get access to all the variables in a tuple at the same time, we can also do this:
aPoint = (10.1,12.3) anotherPoint = (x:10.1,y:12.3)
Suppose I needed polar coordinates, ones based on the radius and angle in degrees, but I only need to use this for a few calculations. Instead of spending time making a struct, I can declare it as a tuple in the function or method.
var radialPoint = (radius:10,angle:0)
Then use it in code somewhere. Suppose I have a method which places pepperoni slices at a polar coordinate on a pizza. Here is a code fragment to place the pepperoni at 30 degree increments from each other in a circle.
angleIncrement = 30 while radialPoint.angle < 360.0{ placePepperoni(distanceFromCenter:radialPoint.radius, rotation:radialPoint.angle) radialPoint = ( 10, radialpoint.angle + angleIncrement) }
This example could be done without a tuple of course, but note that in related values, such as coordinates, it makes for better documentation of code. This will also come in handy in handling the key and value pairs of dictionaries, which we will discuss in more detail next time when we discuss dictionaries.
Returning Multiple Values
Suppose I needed a converter from a CGPoint
value to polar values. I would need to return two values instead of the usual one. I could just set up a struct somewhere else in my code, then assign return to that cutom type, but there are times I’m only going to be needing that data once or twice. Assigning it in several other places gets cumbersome. This is the biggest reason swift has tuples: We can return tuples, and when we do, we return multiple values. For example, look at this fragment of code:
func cartesianToPolar(point:CGPoint)->;(radius:CGFloat,angle:CGFloat){ /* do some math here to get radius and angle */ return (radius,angle) }
I’ll leave the math to those who like trignometry, but for the example there are some conversion formulas to return a polar coordinate from a CGPoint
. The polar coordinate has two values not just the one we usually have. I dedeclare what the tuple will look like in the return part of line one and assign the values in the return statement in line 3. Getting the values out of the function might look like this:
let polarPoint = cartesianToPolar(CGPointMake(5.0, 5.0)) println( "The polar point is\(polarPoint.radius) for the radius and \(polarPoint.angle) for the angle")
Which is pretty easy to deal with.
Tuples can be confused with a lot of other types, like arrays and structs. They are not a full collection types, nor are they full structs. They are a way of making temporary struct-like objects. Their main purpose is to return multiple values with multiple types from a function. In that they excel, and provide developers a new way to write functions.
Leave a Reply