Get introduced to the basic syntax for defining functions in Swift. Optionally specify different external parameter names or omit external names altogether at the call site.
- [Instructor] Functions are blocks of reusable code that perform a task. Functions can be defined as stand-alone global functions or as methods of a type, such as a class. To repeat, methods are just functions of a type in Swift. And functions themselves are reference types. To define a function, write the func keyword, followed by the name of the function, such as sayHelloWorld, a pair of parentheses to enclose the function's input parameters, if there are any, and curly braces to enclose the function's body. Even if there are no parameters, empty parentheses must still be written.
And the naming convention is to use camel casing, beginning with a lowercase letter. Then, in the body of the function, write one or more statements to execute when the function is called, such as printing "Hello, world!" Parameters are written as name-type pairs, similar to how you explicitly declare a variable or constant type. Functions can have no parameters, as I just showed you, or they can have one or more parameters. I'll define a sayHelloTo function. It will take a parameter name of type String.
And then print Hello to that name. Functions can also have multiple parameters, separated by commas in the parameter list. I'll define a function "say" that takes two parameters, greeting of type String and to also of type String. And "say" will just print the greeting to the to. Now, I'll call that function. What is displayed when you call a function is called the external parameter name.
What a parameter was referred to internally within the function is called the local parameter name. A function's parameters automatically have the same external and local parameter names by default. And notice that when you call a function, the first parameter name is displayed. If you're coming from Swift 2, you were used to the first parameter being automatically omitted. Now, if you want to ignore the first parameter at the call site, you must explicitly ignore it by writing an underscore before the parameter name in the definition. And I'll accept the Fixit suggestion to remove the first parameter in the call.
Writing the underscore before a parameter name explicitly suppresses displaying that name externally. So now this function reads nicely at the call site: say("Goodbye", to: "Hollywood"). But using the word "to" internally for the local parameter name is not ideal. To what? You can explicitly define an external parameter name for a parameter by writing it before the local parameter name in the parameter list. If you do, that external name will be displayed when calling the function instead, while the local parameter name will be available within the function. For example, I'll use "to" for the external name and "name" for the local parameter name.
Functions can optionally return a value. To indicate that a function does return a value, write the return arrow, a hyphen, and a right-angle bracket, followed by the type of the return value after the parameter list and before the opening curly brace. I'll define an add function that takes two Int parameters and returns an Int. The result of adding a plus b is passed back from the function using the return keyword. And notice that I explicitly omitted the external parameter names from both parameters by writing underscores.
So, calling add only takes a comma-separated list of two integer values with no parameter names displayed. This is all fine and good, except callers can't tell by the function name just how many Int's they can pass to it. They might try to do this, for example. That's not going to work. But there is a way to specify that a single parameter can take a variable number of values. This is called a variadic parameter. And you define one by writing three periods after the parameter type in the function definition.
A variadic parameter can take zero or more instances of the type specified in a comma-separated list, which will be made available as an array of that type in the function's body. I'll use the reduce function to sum the ints array values. Reduce's first parameter is the initial value, which I've set to zero. And the second parameter is a combining operation. I'm using the plus operator. This combining operation is actually a closure. I'll get into those a little bit later on. So now, when calling the add function with the variadic parameter, I can pass as many int values in a comma-separated list as I wish.
The print function also happens to use a variadic parameter. I'll option-click on it and show that the first parameter is a variadic parameter of Any. Also notice that the separator and terminator parameters have default values, which is why I can optionally omit them when I'm calling print. Parameters are constants by default, so they cannot be modified within the function body. If you want to mutate a parameter value, say from a variable that is defined before the function is called, write the inout keyword before the parameter's type in the definition.
If you're coming from Swift 2, take note that the inout decoration was moved from being a parameter name attribute to a type attribute in Swift 3. By marking the score parameter type as inout, the value will be copied in and mutable. And the function will copy back and replace the original value with the mutated value. I want to repeat that. With inout parameter types, the value is copied in, mutated, and then copied out, replacing the original value. You should not attempt to modify the original value, studentsScore in this case, in the function body, because those changes would be overwritten when the mutated value is copied back out.
For this reason, only variables can be passed in to inout parameter types. And when calling a function with an inout parameter type, the value must be prefixed with an ampersand to indicate that is being passed in as an inout parameter type. You might know from previous experience that prefixing a parameter with an ampersand is intended to convey that it's being passed by reference. And yet I just finished explaining that the value is copied in. In actuality, the value is being passed in at a memory address, and it is actually passed in by reference. This is an optimization and an implementation detail.
Don't overthink things here. Think that the ampersand simply means the value can be modified by the function. And, by the way, a function's function type is its input parameter types and its return type if it does return a value. The function type does not include the function's name or parameter names. So, add is a function type that takes a variadic int parameter and returns an int. And apply extra credit to score is a function type that has two double parameters and does not return a value.
Learn how to write code, understand Swift's key concepts and best practices, and strengthen your programming problem-solving skills. Instructor Scott Gardner teaches the fundamentals, so you'll be prepared to develop applications for iOS, macOS, and other platforms. Completing this course will enable you to not only write first-class code, but to think like a Swift developer.
- Creating playgrounds
- Defining variables and constants
- Working with characters and strings
- Working with collections and groups
- Using operators and defining custom operators
- Controlling program flow
- Defining functions and closures
- Working with classes, structures, and enumerations
- Adopting protocols