Leave a rating/review
Notes: 35. Introduction to Functions
Update Notes: The student materials have been reviewed and are updated as of October 2021.
Functions are a core part of many programming languages. Simply put, a function lets you define a reusable block of code that performs a task.
Then, whenever your app needs to execute that task, you can run the function instead of having to copy and paste the same code everywhere. OK! Let’s jump right in and start writing functions.
Let’s create a simple function that just prints out a string. I’ll choose “Hello”. To write that, I’ll start with the keyword func:
func
Then add the name of the function, “printHello”, with a pair of parenthesis right after it:
func printHello()
And finally, I’ll add a pair of curly braces to create the body of the function. If you type the first one, the second should auto-complete for you when you press return:
func printHello() {
}
-
This part, here, is called a function declaration.
-
The part inside the curly braces is the body of the function. Just like with loops and if statements, that’s where you put the code you want to execute.
I said I just want this function to print out “Hello!”. You know how to do that, already!
func printHello() {
print("Hello!")
}
Then, to use the function, you need to “call” it. To call a function, just type the name of the function followed by parenthesis:
printHello()
-
Once you’ve called the function, the code inside of the body will execute, and you can check your results in the sidebar,
-
and in this case, because we’re using
print, we also get results in the console! -
This process might seem familiar! If you built the Bull’s Eye app, then you probably remember writing methods like
startNewGame. -
So what’s the difference between the methods you wrote in Bull’s Eye, and this printHello() function? Why is one called a function and the others methods?
-
This function isn’t part of a struct or class. The methods in Bull’s Eye all belonged to the struct they were defined in!
This is an important point you remember know about terminology: you may hear people use the terms “function” and “method” interchangeably, because methods are essentially functions that belong to another type.
Even though they’re similar, we recommend being specific when you talk about your code.
You may also hear the term “free function” used to specify the kind of function I’m talking about. It’s “free” because it isn’t owned by a named type like a struct or class. Enough about terms, let’s get back to coding!
This printHello function simply prints out a message. You probably noticed it’s the same message every time you call the function.
printHello()
printHello()
-
printis actually a function, too. But when you useprint, you can add whatever string you want to be printed to the console inside of parenthesis.
You’ll often want to parameterize your function, just like print! That means you want the function to do something differently depending on the data passed into it via its parameters. For example, take a look at this code from way back in part one of this course.
- To find out if both students passed, I had to write two nearly identical expressions.
let chrisPassed = chrisGrade >= passingGrade
let samPassed = samGrade >= passingGrade
I can avoid that code duplication by wrapping the expression in a function that takes a grade as a parameter. Start with the func keyword, again, and call this function “printPassStatus”.
func printPassStatus
And finished up the declaration with a pair of parenthesis and then curly braces.
func printPassStatus() {
}
- The parameters go inside of the parenthesis, in what’s called a parameter list.
I’ll add one parameter called “grade” and make it an Int.
func printPassStatus(grade: Int) {...
- The syntax for parameters is similar to what you use to declare variables and constants. You name the parameter, then add a colon, then specify the type.
Declaring a constant is actually what you’re doing! Every parameter becomes a constant you can use inside the body of the function. Because they’re constants, they can’t be modified. So if you tried to do something like double the grade…
grade * 2
You’d get an error, just like you would if you had declared a new constant in the function body with “let”.
Now I can use this grade parameter in an expression like the ones above to find out if it’s a passing grade.
❌ grade * 2
print(grade >= passingGrade)
If you want to add a more descriptive print statement, you can use a conditional operator to print “You passed!” if the expression is true or “Keep studying.” if it’s false.
print(grade >= passingGrade ? "You passed!" : "Keep studying.")
To find out if that works, I need to call the function. When you call a function that uses parameters, you need to pass in arguments.
printPassStatus(grade: samGrade)
-
I called the function using the
samGradeconstant as an argument. -
You can see that the parameter name shows up here, but at the call site it’s called an argument label.
The terms “parameter” and “argument” are easily mixed up, but it will help you clearly think and talk about your code if you can remember which is which.
-
A function declares its parameters in its parameter list.
-
When you call a function, you provide values as arguments for the function’s parameters.
Functions can have more than one parameter. So if I want the option to change the lowest passing grade, I can do that by adding another parameter to the function.
When you add more than one parameter to the parameter list, you just comma separate them, like this:
func printPassStatus(grade: Int😺, lowestPass: Int🛑) {...
Now in the body of the function, replace passingGrade with the new parameter.
print(grade >= 😺lowestPass🛑 ? "You passed!" : "Keep studying.")
-
If you’re following along, the Playground should show you an error at this point. The function call is missing an argument to match that new parameter!
-
You can use the Fix It to let the playground add the argument label, or add it yourself.
-
I’ll make it a little tougher for Sam to pass this time.
printPassStatus(for: samGrade😺, lowestPass: 80🛑)
And there’s Sam’s pass status in the console.
-
If you option-click on
print, and scroll down to the bottom of the documentation, you’ll see it actually has three parameters. -
I’m only been using this first one. So how am I calling the function without providing three arguments?
-
The answer is “default values”. Print actually has default values for the second two parameters!
You can add default values to parameters with the same syntax you use to set values for variables.
- Use the assignment operator, that’s a single equals sign, and the default value you want.
func printPassStatus(grade: Int, lowestPass: Int 😺= passingGrade🛑) {...
Now, I can call the function with just the first argument:
printPassStatus(grade: chrisGrade)
You might have noticed one more difference between calling print and calling my printPassStatus function.
-
There’s no argument label when we call
print. You just put the argument inside the parenthesis.
In the parameter list, you can add an argument label that’s different from the parameter name, but you can also say you don’t want an argument label at all. For example, if I write a function to print the highest grade when given two grades…
func printHighestGrade(grade1: Int, grade2: Int) {
print(grade1 >= grade2 ? grade1 : grade2)
}
Neither of those parameter names are really necessary when I call the function.
printHighestGrade(grade1: chrisGrade, grade2: samGrade)
The function name already tells us exactly what it’s going to do with our arguments.
- Argument labels are defined right before the parameter name in the parameter list. We can use our old friend the underscore, there, to say “I don’t need an argument label for this parameter”:
func printHighestGrade(😺_ grade1: Int, 😺_ grade2: Int) {
Now I can leave off both argument labels at the call site and simply separate the arguments with parenthesis:
printHighestGrade(chrisGrade, samGrade)
In this particular function, I’m following Apple’s naming guidelines. If you have arguments that can’t be “usefully distinguished”, you can leave off all of the argument labels.
- Here, all I’m doing is comparing two numbers and printing the highest value. It doesn’t matter which number is assigned to which parameter.
Technically, you could use underscores for all of the argument labels in all of your functions, no matter what you’re doing with them, but wouldn’t I recommend that. It can be challenging to remember how to call your functions, or figure out what a function is planning to do with the arguments you pass in.
You can also assign an argument label that differs from the parameter name.
With Swift, it’s common to hear that you should try to make your function calls read like sentences. I can try that with the printPassStatus function by giving grade an argument label of for:
func printPassStatus(😺for 🛑grade: Int, lowestPass: Int = passingGrade) {...
And then I need to adjust the function calls to match:
printPassStatus(😺for🛑: samGrade, lowestPass: 80)
printPassStatus(😺for🛑: chrisGrade)
- When you have an argument label that’s different from the parameter name, you’ll sometimes hear it called an “external name” or “external parameter name”. That’s because you use it outside of, or external to, the function.
Choosing to use prepositions as argument labels like this is a stylistic decision. Apple has their own recommendations, like the one I cited about when to leave off argument labels altogether.
- These functions are printing out results, but what if I want to do something else with the results, like store them in variables or use them in expressions?
For that, I’ll need to make the function return something. I’ll show you how to return values and talk more about function naming conventions in the next episode.