Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

array
An ordered list of values of one type, reached by position starting at zero.
block
A group of lines of code that run together, often inside curly brackets.
closure
A piece of code you can store in a value and pass to other code, remembered with the names around it.
compiler
The program that turns the code you write into something the machine can run, reporting mistakes before it does.
dictionary
A collection of key and value pairs, where each key appears once and finds its value.
enum
A type whose value is one of a fixed set of named cases, which may each carry extra data.
expression
A piece of code that produces a value, such as a sum or a call to a function.
function
A named piece of code that takes values and returns a result when called.
guard
A check that must pass before the code after it runs, leaving the scope early when it fails.
method
A function that belongs to a type and is called on a value of that type.
nil
The absence of a value, allowed only where a type says a value may be missing.
operator
A symbol such as plus or equals that combines values into a new one.
optional
A type that either holds a value or holds nothing, written with a question mark after the type.
optional chaining
Writing a question mark before something you reach into, so the result is nil when the value is missing.
property
A named value that belongs to a type or to one of its values.
protocol
A list of requirements that a type promises to meet, so code can work with any type that meets them.
scope
The region of code where a name can be used before it goes out of reach.
string interpolation
Putting a value inside text with a backslash and parentheses, so the value becomes part of the text.
struct
A type that groups related values and makes a copy whenever it is given another name or passed along.
subscript
A way to read or write an item in an array or dictionary by putting a key or position in square brackets.
type
What kind of value something is, such as a whole number or text, and what it can do.
unwrap
To get the value out of an optional after checking that something is there.

Swift from the ground up

Functions and their labels

Naming a step, handing values in, returning a result, and the argument labels that make a call read like a sentence.

Part 6 of 12

Intermediate16 min readBack to Courses

Give a step a name

A function collects steps under one name so you can run them again with a single call. You write func followed by the name, a pair of parentheses and a block.

Nothing inside the block runs until you call the name. Calling it is the name followed by parentheses, and a function with no result simply does its work and returns.

A function declaration is not a step that runs where it appears. Swift records the name and its shape, and the body waits until a call. That is why a function can be called on a line above its definition: the compiler has already seen the whole file by the time the call is checked.

Handing values in and out

The parentheses list the values the function needs, each with a name and a type, such as width: Int. The arrow and a type say what comes back, written -> Int.

Inside the block, return hands the answer back and ends the function. A function whose work is only to print has no arrow and returns nothing.

A function with no arrow returns Void, which is a real type with exactly one value. You can write -> Void if you like, but leaving the arrow off means the same thing. If a function returns a value and the caller ignores it, Swift warns unless the function is marked @discardableResult, because an ignored answer is often a mistake.

Labels and defaults

In Swift a call reads like a sentence because each argument carries a label. area(width: 3, height: 4) is clearer than three bare numbers, and the labels come from the function itself.

An argument can have a default. exponent: Int = 2 lets callers leave it out, so power(5) uses two and power(2, exponent: 3) asks for three. A leading underscore on a parameter name removes its label when the meaning is already obvious.

The two names in func greet(person name: String) have different jobs. person is what the caller writes, and name is what the body uses. A call reads greet(person: "Ada"); inside the body you write name. When the two would be the same word, one name is enough: func area(width: Int) gives both the label and the internal name width.

The signature is a contract

A function’s signature is its name together with the labels, the argument types and the type it returns. Callers depend on that shape, so the compiler checks every call against it before the program runs.

Inside the body, the parameters behave like constants. A function can read them but cannot assign to one, which keeps a call from changing the caller’s value behind its back. When the answer is known early, return hands it back and skips the rest of the block.

Argument labels are part of that contract: they make a call read like a sentence and can be omitted with _ when the meaning is obvious.

A call, step by step

Take area(width: 3, height: 4). The compiler matches the labels against the definition, checks that both values are Int, and only then runs the body. Inside, width and height are fresh constants holding 3 and 4. The multiplication produces 12, return hands it back, and the call site receives an Int that it can print or store.

power(2, exponent: 3) follows the same path with one difference: the first argument has no label because the definition writes _ base. The second keeps its label, so the call must say exponent:. If you leave it out, the compiler reports a missing argument rather than guessing which value you meant.

A function, a result and a default

func greet(name: String) {
    print("Hello,", name)
}

func area(width: Int, height: Int) -> Int {
    return width * height
}

func power(_ base: Int, exponent: Int = 2) -> Int {
    var result = 1
    for _ in 1...exponent {
        result *= base
    }
    return result
}

Three mistakes are common at the call site. A function that promises -> Int must return an Int on every path, not only the last one. The label you write when calling is the external name, so greet(person: "Ada") is right for func greet(person name: String), not greet(name: "Ada"). And parameters are constants inside the body, so assigning to one is an error.

Four small functions

Run it and watch each call print its result. Then call `power` with no exponent, and once more with an exponent of three, and predict both answers first.

Output
Click "Run" to execute your code

Try these next

  • Write one function with a labelled parameter and one with an unlabelled parameter, then compare the two call sites.
  • Add a default to a parameter and call the function with and without that argument.
  • Write a function that returns early for an invalid input instead of nesting the rest in an else.

A report with a default

Run it and check each grade. Then change Alan’s score and Grace’s total, and predict the percentages and grades before the next run.

Output
Click "Run" to execute your code

Good names carry the meaning. A function called area and a label called width spare the reader from reading the body to find out what the numbers were.

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What is the purpose of an argument label such as width:?