Chapter 4: Functions

Functions are a core component in programming. They are building blocks in building functional applications. Functions help our code to be more readable, compartmentalized, and ultimately more efficient. We can write a function to perform a specific task and then reuse it at will throughout our application.


What you will learn

  • Creating your first function
  • Another function example
  • Constants

Key Terms

  • Function: a container for a block of code that performs a specific singular task.
  • Parameter: a value passed into a function. Can be of any type.
  • Constant: a value in code that cannot be changed.

Every day, most humans live their lives under a set of routines. Things they do often times without even thinking about or realizing that they're doing them.

Think about what you do when you first wake up. I know for myself, I slither out of bed and stumble across the room to my noisy phone and silence the alarm. That event alone contains several different steps that I follow in the same order every day (unless I forget to set my alarm).

  1. Wake up to alarm sound
  2. Slide out of bed, trying not to accidentally wake my wife.
  3. Stagger my way over to my alarm.
  4. Silence my alarm.

The steps above are a function. A set of steps that I complete over and over again (every morning). In pseudo code, this could look like:

var awake = false
var inBed = true
var walking = false
var alarmSilenced = false

func getUp() {
    awake = true
    inBed = false
    walking = true
    alarmSilenced = true
}

Functions run the code inside them asynchronously, or, in a top-to-bottom manner. How's that for a five-dollar word?

In other words, awake gets set to true, inBed gets set to false, walking gets set to true, and alarmSilenced gets set to true – in that order.

My waking up metaphor is imperfect however, because it takes me probably 10-15 seconds to fully wake up, walk over, and silence my alarm. Modern devices can process the code inside functions so quickly that it is almost as if it's running instantly, even though it is running asynchronously.

Most simply put, functions are a way to perform an operation over and over. You will use them throughout many of the advanced projects you will complete later on in this book.

But enough talking about functions... Let's write some!

Creating your first function

If you've taken any advanced math courses, you probably have some background knowledge regarding functions. You probably know them by another name: Formulas. You can use L x W (length multiplied by width) to calculate the area of a rectangle or a2 + b2 = c2 to determine the length of the hypotenuse of a right triangle.

We will create one of these formulas in Swift to illustrate how functions work. 🙂

First, open Xcode if you haven't already and click Create New Playground. Give it a name like Functions and click Next. Choose somewhere to save this .playground file and click Create to save it. You should see a screen like the one in Figure 1.4.1.

Figure 1.4.1 Screen Shot 2016-10-10 at 5.01.11 AM.png

Delete all the boilerplate code on the left side but leave import UIKit as it is necessary.

To declare a function, we need to:

  1. Begin with the keyword func.
  2. Give it a descriptive name, similarly to how we name variables.
  3. Include a set of parentheses and inside that any parameters we want to pass in. 4.) Declare what value the function should return, if any.

In your Playground, type the following:

func calculateArea(length: Int, width: Int) -> Int {
//Code to calculate the area will go here.
}

As it currently exists, we have declared a function called calculateArea(width:height:). There is no code inside our function and we are passing in a value for the length and width – both of type Int. We have also declared that we want to return a value of Int by typing -> Int. Let's add some code to calculate the area.

func calculateArea(length: Int, width: Int) -> Int {
    let area = length * width
    return area
}

Our function is now complete. We've created a function that calculates the area of a rectangle. We can pass in a value for the length and width (both are required) and the code inside the function multiplies them together to give us an area value. We then return the value of area to our function. But in Playground, our function doesn't print to the console like it should.

That's because we haven't called it yet. We need to type the name of our function and pass in values for length and width so that Xcode knows to run the code inside.

At the bottom of your Playground window, call the function by typing it's name. Use Xcode's AutoComplete feature and press the Enter key when it pops up to make your life easier. Pass in a length of 10 and a width of 20.

func calculateArea(length: Int, width: Int) -> Int {
    let area = length * width
    return area
}

calculateArea(length: 10, width: 20)

To see the result of our function, look at the right-hand side of the Playground window (Figure 1.4.2) to see the value our function returns from our area variable.

Figure 1.4.2 Screen Shot 2016-10-11 at 4.41.09 AM.png

Let's try calling it again but pass in different values to calculate a different area (Figure 1.4.3).

func calculateArea(length: Int, width: Int) -> Int {
    let area = length * width
    return area
}

calculateArea(length: 10, width: 20)
calculateArea(length: 24, width: 15)

Figure 1.4.3 Screen Shot 2016-10-11 at 4.43.26 AM.png

As you can see, the function works with a rectangle of any area with side lengths that are whole numbers.

Another function example

Functions can be used for anything! We used them above for a simple area calculation and now we will write one about our bank account.

At the bottom of your Playground file, type the following:

var bankAccountBalance = 500.00
var selfLacingNikes = 350.00

We created two variables – one to manage our bank account balance and one to declare the price of some cool self-lacing shoes. Great Scott!

We could just write out the conditional code to say that if we have enough money, then we can buy the shoes but a function is an even better way to do this. This way, we can reuse the function and apply it to other item prices.

var bankAccountBalance = 500.00
var selfLacingNikes = 350.00

func purchaseItem(currentBalance: Double, itemPrice: Double) -> Double {
    if itemPrice <= currentBalance {
        print("Purchased item for $\(itemPrice)")
        return currentBalance - itemPrice
    } else {
        print("You are broke. Balance still at $\(currentBalance)")
        return currentBalance
    }
}

What just happened?

Alright, woah. 😳 That was a lot of code to write without any explanation. Let's talk about that now.

We declare a function named purchaseItem(currentBalance:itemPrice:). We gave it two parameters to accept input values – currentBalance and itemPrice. Next, we asked our function to return a value of type Double after it has finished running.

Inside our function, we wrote that if the itemPrice we pass in is less than or equal to our currentBalance value we passed in, then we should 1.) print Purchased item for $\(itemPrice) and 2.) return currentBalance minus our item's price.

If that condition cannot be met, or in our code: else, our function will 1.) print: You are broke. Balance still at $(currentBalance) and 2.) return the value of our current balance unchanged.

At the bottom of our Playground, let's call our function now.

var bankAccountBalance = 500.00
var selfLacingNikes = 350.00

func purchaseItem(currentBalance: Double, itemPrice: Double) -> Double {
    if itemPrice <= currentBalance {
        print("Purchased item for $\(itemPrice)")
        return currentBalance - itemPrice
    } else {
        print("You are broke. Balance still at $\(currentBalance)")
        return currentBalance
    }
}

var bankAccountBalance = 500.00
var selfLacingNikes = 350.00

//Pass in the values for "bankAccountBalance" and "selfLacingNikes" below.

purchaseItem(currentBalance: bankAccountBalance, itemPrice: selfLacingNikes)

As you can see on the right-hand side, the function works! Our item's price is less than our account balance, so the operation 500.00 - 350.00 takes place for the price of the shoes to be subtracted by our account balance. This gives us a bankAccountBalance value of 150.00.

To actually do something with that value, we can override our bankAccountBalance to update it after our function runs.

...

bankAccountBalance = purchaseItem(currentBalance: bankAccountBalance, itemPrice: selfLacingNikes)

Now bankAccountBalance is equal to 150.00 instead of 500.00 because our function has modified it AND we printed a message to the Debug menu (Figure 1.4.4).

Figure 1.4.4 Screen Shot 2016-10-11 at 5.24.10 AM.png

We can create a new item to buy and pass it in through our function, too!

Create a variable beneath selfLacingNikes named stainlessSteelAppleWatch and give it a price of 599.00 like so:

var bankAccountBalance = 500.00
var selfLacingNikes = 350.00
var stainlessSteelAppleWatch = 599.00

Now pass it in to our purchaseItem(currentBalance:itemPrice:) function:

...
bankAccountBalance = purchaseItem(currentBalance: bankAccountBalance, itemPrice: stainlessSteelAppleWatch)

As you can see in Figure 1.4.5, our function prevents the purchase from being made and prints out an error message for us.

Figure 1.4.5 Screen Shot 2016-10-11 at 5.59.16 AM.png

String Interpolation

As an aside, let's talk about why I used \() and placed itemPrice inside of it i.e. \(itemPrice).

In Swift, when you want to print a message or create a String value and include a value of a different type, we can pass it in and convert it using String Interpolation. Like so:

var price = 250
var message = "The item's price is $\(price)."

The message that will print to the console is: "The item's price is $250."

The variable price is of type Int (inferred by Swift) and it's passed in and interpolated by using the syntax \(). Pretty cool!

Return Values Are The End of the Road

Whenever you call a return in a function, that is the end of that function. Code written after a return will never run. So make sure that any code written goes before the return statement.

Here's a bad example:

var pizzaSlices = 8
var amountOfPizzaEaten = 2

func eatPizza(slicesEaten: Int, pizzaSlices: Int) -> Int {
    if slicesEaten >= 1 {
        let updatedSlices = pizzaSlices - slicesEaten
        return updatedSlices
        print("\(updatedSlices) slices of pizza left!")
    } else {
        print("Meh, not hungry.")
        return pizzaSlices
    }
}

eatPizza(slicesEaten: amountOfPizzaEaten, pizzaSlices: pizzaSlices)

Do you smell something funky? In programming, we actually call this a "code smell" – when something just ain't right.

The print function called after return will never run because it was called too late. In fact, Xcode will even warn us that the code written afterward will not run. Our function SHOULD look like this:

var pizzaSlices = 8
var amountOfPizzaEaten = 2

func eatPizza(slicesEaten: Int, pizzaSlices: Int) -> Int {
    if slicesEaten >= 1 {
        let updatedSlices = pizzaSlices - slicesEaten
        print("\(updatedSlices) slices of pizza left!")
        return updatedSlices
    } else {
        print("Meh, not hungry.")
        return pizzaSlices
    }
}

eatPizza(slicesEaten: amountOfPizzaEaten, pizzaSlices: pizzaSlices)

Choosing To Not Return Anything

What if we don't want to deal with return values? Well, thanks to inout parameters, we don't have to. An inout parameter allows for us to directly modify variables outside our function instead of having to return a value to them in order to update their value.

You can use an inout parameter by modifying the pizza function we wrote above:

var pizzaSlices = 8
var amountOfPizzaEaten = 2

func eatPizza(slicesEaten: Int, pizzaSlices: inout Int) {
    if slicesEaten >= 1 {
        pizzaSlices = pizzaSlices - slicesEaten
        print("\(pizzaSlices) slices of pizza left!")
    } else {
        print("Meh, not hungry.")
    }
}

eatPizza(slicesEaten: amountOfPizzaEaten, pizzaSlices: &pizzaSlices)

Inside the if block of our function, we are able to directly modify the variable pizzaSlices which is super cool. When we call the function eatPizza(slicesEaten:pizzaSlices:) we add an ampersand to the front of the pizzaSlices variable we pass in. This is the syntax to tell Xcode that we want to use an inout parameter.

By writing a function this way, we aren't required to return a value but we can still modify the variables we want. You want to use this sparingly, and you don't need to know about this yet, but it's good to have in your tool-belt.

Constants

Throughout this chapter, you have seen the keyword let used in a similar way to how we create variables. That keyword is actually incredibly important. It is used to declare a Constant in Swift.

A constant is exactly like a variable except for the fact that it can never change once it is given a value.

Some examples of data that could be constants are: your birthday, a city name, car model, etc. Things that never change and remain constant (hence the name!). The keyword let is used in a "let that value stay the same" kind of manner.

Here are some pseudo-code examples:

let birthYear = 1992
let mothersMaidenName = "Squillagree"
let jennysPhoneNumber = 8675309

These values are all unchanging and we won't need to change them. If we try to change them, Xcode will yell at us and give us an error asking us to change our let into a var so it can be modified as in Figure 1.4.6:

Figure 1.4.6 Screen Shot 2016-10-11 at 7.48.05 PM.png

To be honest, that is the only information you will need to know about constants as they are identical to variables except that they cannot be changed once given a value.

Wrapping up

We've learned a lot in this chapter about functions – reusable bits of code that perform specific tasks. 99.9% of coding is writing and using functions so this is very important for you to know and understand well.

We talked about the anatomy of a function which contains the keyword func, a descriptive name of what the function does, a set of parentheses optionally including parameters to pass in, and a return type if needed.

In the following chapters, you will use functions frequently so if there are any parts of this chapter you don't fully understand read back through it again and make sure you really get it down.

Exercise

Write a function called canDivideSlices that takes in two values – numberOfSlices and numberOfFriends and returns a value of type Bool(true or false). This function will be used to determine whether or not a pizza can be divided evenly by your group of friends.