Day 5 - 100 Days of Swift

5 minute read

Functions

Day 5 is about Functions. You look at writing functions, how to accept parameters and return values. You look at labelling parameters, omitting parameter labels and giving default values to parameters. You look at variadic parameters, writing and running functions that throw errors, and passing inout parameters to functions.

You can make your code more readable, more reusable, and a lot shorter by sticking chunks of code into a function. In Swift that looks like this:

1
2
3
4
5
6
7
func annoyTheJanitor() {
    print("Put a penny in the door")
}

annoyTheJanitor()
// Prints:
// "Put a penny in the door"

You can make functions more customizable by adding the ability to pass in parameters when you call it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func drCoxExtendsAWord(word: String, syllables: Int) {
    let firstSyllable = word.prefix(2)
    let lastSyllable = word.suffix(word.count-2)
    var result = ""
    result += firstSyllable
    for _ in 0..<syllables {
        result += "..he"
    }
    result += lastSyllable
    print(result)
}

drCoxExtendsAWord(word: "Really", syllables: 3)
// Prints:
// "Re..he..he..heally"

You can also pass a value back:

1
2
3
func whyIsThereAPancakeInTheSilverwareDrawer() -> String {
    return "I think you mean why is there silverware in the pancake drawer?"
}

You can add to the readability by using parameter labels. These are used when you call the function:

1
2
3
4
5
6
7
8
9
func areTurkAndCarlaMarried(in season: Int) -> Bool {
    if season > 3 {
        return true
    }
    return false
}

areTurkAndCarlaMarried(in: 5)
// returns true

You can also omit the parameter label all together if you want:

1
2
3
4
5
6
7
8
9
10
11
12
func toddGivesHighFiveFor(_ reason: HFReason) {
    switch reason {
    case .innuendo:
        print("I'd hit that")
    case:
        print("High five!")
    }
}

toddGivesHighFiveFor(.goodWork)
// Prints:
// "High five!"

If there is a value that you usually want to call a function with, you can give it a default value:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func drCoxExtendsAWord(_ word: String, by syllables: Int = 3) {
    let firstSyllable = word.prefix(2)
    let lastSyllable = word.suffix(word.count-2)
    var result = ""
    result += firstSyllable
    for _ in 0..<syllables {
        result += "..he"
    }
    result += lastSyllable
    print(result)
}

drCoxExtendsAWord("Really")
// Prints:
// "Re..he..he..heally"

drCoxExtendsAWord("Really", by: 2)
// Prints:
// "Re..he..heally"

If you don’t know ahead of time how many parameters you’ll need, you can accept any number by making the parameter variadic:

1
2
3
4
5
6
7
8
func drCoxCallsJDAGirlsName(_ names: String...) {
    let nameString = names.joined(separator: ", ")
    print("Good morning \(nameString)")
}

drCoxCallsJDAGirlsName("Betsy", "Lauren", "Molly")
// Prints
// "Good morning Betsy, Lauren, Molly"

If your function can fail, instead of just crashing or continuing in an unproductive state, you can throw an error:

1
2
3
4
5
6
7
8
9
enum HealthError: Error {
    case heartStopped
}

func revivePatient() throws {
    if heartbeat == 0 {
        throw HealthError.heartStopped
    }
}

When you run a function that throws, you have to mark it with try. That’s basically you telling the compiler that you know the function might fail and you’re prepared to deal with it:

1
2
3
4
5
do {
    try revivePatient()
} catch {
    print("Couldn't save them.")
}

Usually parameters are passed as constants, but if you need to make a change to a variable inside of a function you can mark it as inout and precede it with an & when you call the function:

1
2
3
4
5
6
7
func transplant(_ heart: inout Heart) {
    let newHeart = Heart.fromDonor()
    heart = newHeart
}

var badHeart = patient.heart
transplant(&badHeart)

Reflections

Some of these things feel like the basics to me, but some of them feel like more advanced, or at least less common, features of Swift functions. The order he is following is not the typical intro to Swift order that I’ve seen in other places. Throwing errors and variadic parameters and inout parameters, all of them feel to me like things that you figure out when you need them. But I think I like this format where he introduces all of the pieces of the language that relate to the topic of the day, even if they are somewhat uncommon. It gives the people who are new to Swift exposure to the whole breadth of the language, and it gives people like me (who are familiar with the basics) something to chew on too.