Functions

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the last demo, you updated the code for the Fibonacci series to use loops. You’re no longer generating the numbers in the sequence one by one, but you’re able to generate as many numbers as you want by changing how many times the loop repeats.

In this lesson, you’ll learn about functions. They allow you to group parts of your code and execute them as one line. An example of a function you’ve already been using: print.

print does a number of things internally, but you don’t need to know the specifics. All you need to know is that it takes a string as a parameter and shows it on your screen. You’ll learn the syntax of Swift functions (how to declare them), how you can provide one or more inputs to functions, and how to receive output.

This is an example of a function:

func printNumbers() {   //1
  for index in 0...10 { //2
    print("\(index)")   //3
  }
}
  1. It starts with the keyword func to say that this is a function, and its name is printNumbers. It doesn’t receive any input, so the round brackets are empty.
  2. The function has a code block, which is a loop.
  3. The loop iterates over the numbers from zero to 10 and prints them.

To execute this function, you call it with its name and the empty brackets printNumbers(). Your code will execute as if you entered the three lines of the loop.

Functions are meant to provide flexibility in what task they’re responsible for without showing details of the code inside them. For this example of printNumbers, when you execute it, you can’t change anything about what it does. That could feel restrictive when you need to change what the function does slightly. printNumbers prints from zero to 10 and that’s it. What if you want to print from zero to five, or to any other number? In that case, you want to tell the function the end of the range as an input.

To define an input for a function, you define a variable with no default value inside the round brackets beside the function’s name. You don’t use the keywords var or let. Swift automatically makes the variable a let. It can’t be changed inside the function:

func printNumbers(endRange: Int) {
  for index in 0...endRange {
    print("\(index)")
  }
}

To call this function, you pass the value as follows:

printNumbers(endRange: 5)
printNumbers(endRange: 7)

The name of the variable endRange became part of the name of the function. If you want to omit the variable from the name, put an underscore (_) before it:

func printNumbers(_ endRange: Int) {
  for index in 0...endRange {
    print("\(index)")
  }
}

printNumbers(5)

Functions aren’t limited to only one parameter. You can define more than one by separating them with a comma. This is how the function would look if you want to give it the starting and ending numbers:

func printNumbers(startRange: Int, endRange: Int) {
  for index in startRange...endRange {
    print("\(index)")
  }
}
printNumbers(startRange: 0, endRange: 5)
printNumbers(startRange: 6, endRange: 10)

As before, you can also omit the variable names when you call the function by adding an underscore before the name of the variable. You can omit one of the two or both together:

func printNumbers(_ startRange: Int, _ endRange: Int) {
  ...
}

printNumbers(0, 5)

Or:

func printNumbers(startRange: Int, _ endRange: Int) {
  ...
}

printNumbers(startRange: 0, 5)
func printNumbers(_ startRange: Int, endRange: Int) {
  ...
}

printNumbers(0, endRange: 5)

When the function takes one input parameter, it’s often OK to omit its name. But when there are more than one, it’s usually not a good practice to omit parameter names. Parameter names help people calling the function know what parameters the functions needs and in what order. This function takes two inputs; without parameter names, it would be hard to remember which starts the range and which ends it. Then, if you want the function to print the numbers increasing by a different value than one, you might add another parameter. Anyone who wanted to use your function would have to remember all the parameters and their order. The function declaration wouldn’t help at all.

printNumbers(startRange: 6, endRange: 10, increaseBy: 2)

Having those names as part of the function definition removes the need of this guessing and reduces the chances you might mix inputs together and end up with a bug in your app.

Functions can also provide an output. Imagine you want printNumbers to also sum them:

func printNumbers(startRange: Int, endRange: Int) {
  var sum = 0
  for index in startRange...endRange {
    sum += index
    print("\(index)")
  }
}

Now, sum contains the value you need, but how should a function say it can provide an output and the data type of that output? You do this by adding an arrow with the minus sign and greater than symbol (->) followed by the return data type right after the closing bracket that holds the input parameter variables:

func printNumbers(startRange: Int, endRange: Int) -> Int {
...
}

Now, the function says “I will give you an output of type Int”. Now, inside its code block, you must return the sum when you’re done calculating it. The final version of the function should look like this:

func printNumbers(startRange: Int, endRange: Int) -> Int {
  var sum = 0
  for index in startRange...endRange {
    sum += index
    print("\(index)")
  }
  return sum
}

When the loop completes, sum contains the final value you want to use as the output. The keyword return followed by the variable makes the function use that value as an output immediately.

The return keyword ends the execution of the function immediately, like how break ends the execution of a loop. So in this example, if you had return sum inside the loop, the for loop wouldn’t work. Only one number will be printed, and sum will increment only once, which means the function doesn’t do what it’s supposed to do.

In the examples above, you called a function by just writing it on a line. When a function returns a value, you have to use a variable or constant to hold it. So your code to call the function looks slightly different:

var sumVariable = 0
sumVariable = printNumbers(startRange: 0, endRange: 5)
let sumConstant = printNumbers(startRange: 5, endRange: 10)

defer

Swift has a nice keyword that works in both functions and loops, called defer. As a simple explanation, it takes a code block and executes it at the end of the loop or the function. Using it in a loop looks like this:

for index in 0...1 {
  defer {
    print("This is the last line for index: \(index)")
  }
  print("This is the first line for index: \(index)")
  print("This is the second line for index: \(index)")
}
This is the first line for index: 0
This is the second line for index: 0
This is the last line for index: 0
This is the first line for index: 1
This is the second line for index: 1
This is the last line for index: 1
func printNumbers(startRange: Int, endRange: Int) -> Int {
  var sum = 0
  defer {
    print("The sum is: \(sum)")
  }
  for index in startRange...endRange {
    sum += index
    print("\(index)")
  }
  return sum
}
See forum comments
Download course materials from Github
Previous: Loops Demo Next: Function Demo