# Tuples, Structs and Enums

## What are the differences?

Swift has lots of different ways of storing your data. You can use enums, tuples, structs, classes (or even just use malloc and manage it yourself)! In this article, we'll compare enums, tuples and structs. Let's start with the simplest: tuples.

A tuple is a typed list of values. For example, you can define a tuple that holds an integer and a string:

``````let amount = (100, "EUR")
``````

This is very useful when you want to return multiple values from a function. To get the values out, you can use `.0`, `.1` (and so on), or pattern matching. For example:

``````let currency = money.1 // "USD"
``````

If you want to, you can also name the individual elements, to have a bit more documentation:

``````let money = (amount: 100, currency: "USD")
``````

Now, you can still use `.1`, but alternatively, you can also use `.currency`:

``````let currency = money.currency // "USD"
``````

If we want to write a formatter for currencies, we can now do that:

``````func format(input: (Int,String)) -> String {
return "I have \(input.0) \(input.1) in my wallet"
}

println(format(money)) // This prints "I have 100 USD in my wallet"
``````

Our format function works on any `(Int,String)` tuple:

``````let mass = (1, "kg")

let formatted = format(mass) // "I have 1 kg in my wallet"
``````

Clearly, having 1 kg in your wallet doesn't make sense. Therefore, let's introduce a struct. A struct can hold exactly the same kind of a data as a tuple. In addition, you can also define functions on the struct itself (whereas with tuples, you can only define top-level functions). Let's consider the following struct:

``````struct Money {
let amount: Int
let currency: String
}

let wallet = Money(amount: 100, currency: "USD")
``````

This can hold exactly the same kind of data as a tuple, but now we can also define a function on it:

``````extension Money {
func format() -> String {
return "I have \(self.amount) \(self.currency) in my wallet"
}
}

println(wallet.format())
``````

If we want to make a distinctive type for mass, we can now do that:

``````struct Mass {
let quantity: Int
let unit: String

func format() -> String {
return "I have \(self.quantity) \(self.unit) in my backpack."
}
}
``````

Not only do we now have functions on our `Money` type, we also have given it an explicit name. In other parts of our code, we can be certain that we don't accidentally pass in a mass pair (like `(1, "kg")`). A struct is also called a nominal type: it gives an explicit name to a type, and values only have the same type if they share that name. In the example above, `mass` and the first definition of `wallet` have the same type, but values of type `Money` and `Mass` have different types. If we call `format` on them, we get different results.

### Enums

If we want to store some values together, we now know that we can use a tuple or a struct, depending on the use-case. We can also use classes, but that's beyond the scope of this article. However, sometimes we want to represent a choice between some values. For example, let's consider currencies. In the previous example, we've used `String` to use the currency, but what if we want to restrict our program to only currencies we know about? This is where we can use an enum. For example, if we want to restrict our program to only euros, US dollars and yen, we can write the following enum:

``````enum Currency {
case EUR
case USD
case YEN
}
``````

Now, if we have a value of type `Currency`, we know that it will be either `EUR`, `USD` or `YEN`. There is no way it can be of any other value, or multiple of these values at the same time. Just like with structs, you can also define functions on enums:

``````extension Currency {
func symbol() -> String {
switch self {
case .EUR: return "€"
case .USD: return "\$"
case .YEN: return "¥"
}
}
}
``````

We can add as many cases as we want. However, we could also have an enum with a single case:

``````enum Angle {
This is equivalent to having a struct: we can add functions, and it is impossible to accidentally confuse `Angle` values with other `Double` values. However, if we decide that we want to add more cases in the future, we can do this.