In this section, we will learn how to define functions and how to use them in our code. They help us to reuse sequences of statements with ease. We can define a general solution of a problem and then apply it, customized, to different parts of our app. This approach saves time, reduces the potential of bugs in the code, and simplifies huge problems to small ones.
The first function, which we already saw in use, is print(). It's used to display text on the screen. We will experiment with this in the next chapter, once we get our hands dirty with Xcode and Swift.
Now let's define our first function, which executes a sequence of statements in its body:
func printSum() {
let a = 3
let b = 4
print("Sum \(a) + \(b) = \(a + b)")
}
When defining a function, we start with the special word func. Then the name of the function follows and the list of the arguments in brackets ( ) and its returned type. After that comes the body of the function in curly braces { }.
This definition doesn't do anything if we don't call (execute) the function. How is this done?
We have to call the function using its own name as follows:
printSum()
Once a function is called, we may think that the same sequence of code is executed where the function call is made. It's not exactly the same, but we can think of having the body of the function executed line by line.
Now let's see the general form of a function:
func functionName(argumentLabel variableName:String) -> String {
let returnedValue = variableName + " was passed"
return returnedValue
}
//here is the function invocation and how the result is returned
let resultOfFunctionCall = functionName(argumentLabel: "Nothing")
Each function may have no arguments, one argument, or many arguments. Until now, we have seen some without arguments and with a single argument. Every argument has an argument label and a parameter name. The argument label is used when the function is called. This is really useful when we have many parameters. It gives us a clue what data should be passed to that specific parameter when using the function. The parameter name (variable name) is the name which will be used in the function body to refer to the passed value. All parameters should have unique parameter names; otherwise there is ambiguity, and we won't be able to say which one is which.
A function may return a value from a specific type, or it may be void (nothing will be returned). When we want to return something, we have to define that, and this is done with -> and the type of the result. In the preceding code, we see -> String, and this means that the function returns a value of the String type. This obliges/binds us to using the keyword return in the function body at least once. The return keyword immediately stops the execution of the function and returns the value passed. If a function doesn't return anything, we can still use return in its body, and it will work similarly to break in a loop.
We can use _ if we want to skip the label of an argument. Here is a simple piece of code that illustrates that:
func concatenateStrings(_ s1:String, _ s2:String) -> String {
return s1 + s2
}
let helloSwift = concatenateStrings("Hello ", "Swift!")
// or
concatenateStrings("Hello ", "Swift!")
When we don't use the _ (underscore), then the argument name is the same as the parameter name (variable name).
Similar to what we have seen with the labels, we can ignore the returned value once the function is called.
What happens if we want to return multiple values? We can use tuples to return multiple values when executing a function. The following code is an example of this:
//define a function which finds the max element and its index in an
array of integers
func maxItemIndex(numbers:[Int]) -> (item:Int, index:Int) {
var index = -1
var max = Int.min
//use this fancy notation to attach an index to each item
for (i, val) in numbers.enumerated() {
if max < val {
max = val
index = i
}
}
return (max, index)
}
let maxItemTuple = maxItemIndex(numbers: [12, 2, 6, 3, 4, 5, 2, 10])
if maxItemTuple.index >= 0 {
print("Max item is \(maxItemTuple.item).")
}
//prints "Max item is 12."