# Enums and Switches

OCaml programmers rejoice–you'll be back in 3110. For everyone else, don't worry this won't be anything too special (until the advanced sections).

In programming, you will sometimes need to represent a set of states. There are multiple ways to do this, but you will most often see it implemented as a subset of integers that correspond to a specific state–usually denoted in constants. Below we will model what college someone is in using said technique:

```swift
let artsAndSciences = 0
let engineering = 1
let ag = 2
let hotel = 3 
...

let noah = Student(name: "Noah", college: artsAndSciences)
// noah: Student
//     name: String = "Noah"
//     college: Int = 0
```

This works fine if done properly. There is a concern here that the `college` field is technically `Int`; we can pass any integer into the `college` field but it only makes sense if it is an integer that is contained in the constants predefined. For example, the following code would break our example:

```swift
let brokenStudent(name: "Cornell Redditor", college: -1)
// brokenStudent: Student
//     name: String = "Cornell Redditor"
//     college: Int = -1
```

We don't have a `-1` college, so if we ever use this object later, we will have difficulty discerning what that means. In python, we would fix this with assert statements and/or preconditions. This is fine and works in Swift too, but we have a better alternative. Instead of using integers to represent a data type, let's just make a new data type! This is where `enums` come; an enumeration type; a type where all valid states are distinguished.

If we are creating a basic enum, we use the syntax:

```swift
enum <Insert Type Name> {
    case State1
    case State2
    ...
}
```

So for our college example, we could do something like...

```swift
enum College {
    case artsNSciences
    case engineering
    case agAndLifeSciences
    case hotel
    ...
}
```

We can think of each of these states as constructors for a state, so the state constructors are a member of the type itself. In lay-man terms, we can access a state like this:

```swift
let myCollege = College.artsNSciences
// myCollege: College = College.artsNSciences
```

If we are assigning a state somewhere that expects an enum, we can forgo the type. I.e. if we are assigning to a variable or a function, that already has the college type (it is explicitly typed instead of inferred) we just write `.<state>`:

```swift
let myCollege: College = .artsNSciences
// myCollege: College = College.artsNSciences

let noah = Student(name: "Noah", college: .artsNSciences)
// brokenStudent: Student
//     name: String = "Cornell Redditor"
//     college: College = College.artsNSciences
```

### Switch Statements

Another great reason to use enums is switch statements–a very simple version of pattern matching. You can also think of this as a simplification for doing a lot of if-else statements. We will examine how to use switch-statements through an example:

With our students defined in the previous section, let's say we are trying to figure out their graduation requirements. We will build a function that takes in a school, and returns the requirements. For sake of laziness, if the school is one not explicitly listed above, we will just return the swim test. Here's how we would do this with if-else statements:

```swift
func getRequirements(_ college: College) -> [String] {
    if college = .artsNSciences {
        return ["Foreign Language", "Biological Sciences", ...]
    } else if college = .engineering {
        return ["Physics", "Chemistry", ...]
    } else if college = .agAndLifeSciences {
        return ["I don't know"]
    } else if college = .hotel {
        return ["Probably something hotel-related"]
    } else {
        return ["Swim test"]
    }
}
```

This is fine and dandy, but there's a lot of writing, I have to make sure my if-else statements are correct, and I often forget cases when doing more complicated things like this. We can use switch statements to fix this. To use a switch we use the syntax:

```swift
switch <Insert parameter> {
    case someCase:
     <code to execute>
    case anotherCase:
     <code to execute>
    ...
    default:
     <code to execute>
}
```

So, for the above example, we would write it like:

```swift
func getRequirements(_ college: College) -> [String] {
    switch college {
    case artsNSciences: return ["Foreign Language", "Biological Sciences", ...]
    case .engineering: return ["Physics", "Chemistry", ...]
    case .agAndLifeSciences: return ["I don't know"]
    case .hotel: return ["Probably something hotel-related"]
    default: return ["Swim test"]
}
```

Notice that we use `default` to catch cases that have not been handled.

Switch statements can work for many types, but they work especially well with enums because they have such clear patterns that can be handled in unique manners. Moreover, if we ever update our `enum` to include additional states, switches can let us know when we do not cover this case.

### Literals

You want to associate (sorry this is a poor word choice–you'll see why later) your enums with certain values. For example, with the `College` example, we may want to print the college someone is going to:

```swift
func printCollege(_ student: Student) {
    print("\student.college")
}
printCollege(student: Student(name: "Noah", college: .artsNSciences))
// "artsNSciences"
```

It's cool that Swift will allow us to print the state name directly, but seeing as we named our college kind of gross abbreviations, this doesn't necessarily make sense. If want to change this, we can have our `enum` conform to a type, and directly assign values.

```swift
enum College: String {
    case artsNSciences = "Arts & Sciences"
    case engineering = "Engineering"
    case agAndLifeSciences = "Agricultures & Life Sciences"
    case hotel = "Hotel Administration"
    ...
}
```

If you ever need to access these literal values, you can use the `rawValue` property:

```swift
College.artsNSciences.rawValue
// "Arts & Sciences": String 
```

You can also use raw values as an initializer:

```swift
let someCollege = College(rawValue: "Arts & Sciences")
// someCollege: College = College.artsNSciencessw
```

#### Advanced Topics

Enums with Associated Values are a very powerful tool that mimic OCaml types. This can be hard to employ and is not very helpful for UI until you get to Networking!

{% content-ref url="/pages/1A2kz5d27g30OnsUXZNd" %}
[Enums with Associated Values](/resources/swift-foundations/enums-and-switches/enums-with-associated-values.md)
{% endcontent-ref %}

Indirect enums are for those that want to `Fun`ctional. This is a very weird, cool, powerful, and crazy tool. Not really sure when you'd ever use this in UI though ¯\_(ツ)\_/¯.

{% content-ref url="/pages/EczqH2qpsXQZop5jfFQF" %}
[Indirect Enums](/resources/swift-foundations/enums-and-switches/indirect-enums.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ios-course.cornellappdev.com/resources/swift-foundations/enums-and-switches.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
