Swift: Tuples

A tuple in Swift is a construct that groups multiple values together into a single compound value. Tuples can be useful when more than one value type can provide more useful information about the outcome of a behavior or action than simply returning a single value. They are meant to be temporary and are not suited for more complex data structures that will probably persist beyond a temporary scope, however. If you've done some basic Swift programming, then you've probably seen tuples before. Consider iterating through a dictionary or an array using a for-in loop.

for (key, value) in dictionary {  
 // do some stuff...
}


The (key, value) in the for-in loop is one of Swift's use of tuples.

To better understand what a tuple is and how they can be useful, let's examine a real-world example of returning the status code of a successful HTTP request.


Defining a Tuple


HTTP status codes are defined by a code represented as an integer value, and a description of the status code represented by a string. The values in a tuple can be of any type and these types don't have to be the same as each other. To define a tuple, we simply wrap the values in parentheses. Here's an example of defining a tuple representing the status code of a successful HTTP request.

let httpSuccess = (200, "success")  


The tuple defined above can be described as a tuple of type (Int, String).

Named Values

An alternative way to define a tuple is to provide names for each of the values it contains.

let httpSuccess = (code: 200, description: "success")  


Now that we have our tuple, however, we need to extract it's contents to make use of them. There are three ways to extract the httpSuccess tuple defined above.


Accessing a Tuple


Decomposing it's Contents

We can decompose the contents of a tuple by providing the names of the constants or variables within a tuple and assigning the values like we would any other constant or variable.

let (code, description) = httpSuccess

print(code)  
 => "200"

print(description)  
  => "success"
let (onlyTheCode, _) = httpSuccess

print(onlyTheCode)  
  => "200"


Indexing a Tuple

We can also access the contents of a tuple by providing the index position of the value we want. This is similar to how we'd access a value in an array via it's index position; the only difference is that with tuples, we use dot notation.

let code = httpSuccess.0  
let description = httpSuccess.1

print(code)  
 => "200"

print(description)  
  => "success"


Accessing it's Named Values

In the context of a tuple defined with named values, we can access each value by calling the value's name via dot notation.

let httpSuccess = (code: 200, description: "success")

print(httpSuccess.code)  
  => "200"

print(httpSuccess.description)  
  => "success"


Functions and Tuples


Tuples can also be useful as a return type for a function to return multiple values as part of a single compound value. Continuing with our HTTP response code example, let's build out the function that's responsible for returning this tuple.

func getRequest(url: String) -> (code: Int, description: String) {  
  let response = HTTP.get(url)
  return (response.code, response.description)
}
let response = getRequest(url: "http://example.com")

print(response.code)  
  => "200"

print(response.description)  
  => "success"


As seen in the example above, we can optionally provide names for the tuple's values when specifying the return type. Since we specified names for the values of the tuple in the return type, we don't have to specify these names when returning the tuple in the function.

There may be instances, however, where the tuple may have no value at all. To handle these situations, we can declare the tuple to be an optional tuple to indicate that it can be nil. Continuing with our HTTP response code example, suppose an incorrect URL is supplied to the getRequest(url:) method. Given the way it is currently written, this may result in a runtime exception being thrown. To handle this possibility, we can specify the return type to be an optional tuple by adding a ? after the closing parenthesis.

// Optional tuple return value
func getRequest(url: String) -> (code: Int, description: String)? {  
  let response = HTTP.get(url)
  return (response.code, response.description)
}
if let response = getRequest(url: "http://example.com") {  
  print(response.code)
  print(response.description)
}

=> "200"
=> "success"


Summary


Tuples can be useful when more than one value type can provide more useful information about the outcome of a behavior or action than simply returning a single value. They are fairly simple constructs to grasp and though they may not be suitable for every situation, they're another tool in Swift's toolbelt that you should become familiar with.