Publishers of technology books, eBooks, and videos for creative people

Home > Articles

Writing Functions and Closures in Swift

In this chapter from Swift for Beginners: Develop and Design, 2nd Edition, you’ll learn how to tidy up your Swift code into nice clean reusable components known as functions.
This chapter is from the book

I’ve covered a lot up to this point in the book: variables, constants, dictionaries, arrays, looping constructs, control structures, and the like. You’ve used both the REPL command-line interface and now Xcode’s playgrounds feature to type in code samples and explore the language.

Up to this point, however, you have been limited to mostly experimentation: typing a line or three here and there and observing the results. Now it’s time to get more organized with your code. In this chapter, you’ll learn how to tidy up your Swift code into nice clean reusable components known as functions.

Let’s start this chapter with a fresh new playground file. If you haven’t already done so, launch Xcode and create a new playground by choosing File > New > Playground, and name it Chapter 4.playground. You’ll explore this chapter’s concepts with contrived examples in similar fashion to earlier chapters.

The Function

Think back to your school years again. This time, remember high school algebra. You were paying attention, weren’t you? In that class your teacher introduced the concept of the function. In essence, a function in arithmetic parlance is a mathematical formula that takes one or more inputs, performs a calculation, and provides a result, or output.

Mathematical functions have a specific notation. For example, to convert a Fahrenheit temperature value to the equivalent Celsius value, you would express that function in this way:

084equ01.jpg

The important parts of the function are:

  • Name: In this case the function’s name is f.
  • Input, or independent variable: Contains the value that will be used in the function. Here it’s x.
  • Expression: Everything to the right of the equals sign.
  • Result: Considered to be the value of f(x) on the left side of the equals sign.

Functions are written in mathematical notation but can be described in natural language. In English, the sample function could be described as:

  • A function whose independent variable is x and whose result is the difference of the independent variable and 32, with the result being multiplied by 5, with the result being divided by 9.

The expression is succinct and tidy. The beauty of functions is that they can be used over and over again to perform work, and all they need to do is be called with a parameter. So how does this relate to Swift? Obviously I wouldn’t be talking about functions if they didn’t exist in the Swift language. And as you’ll see, they can perform not just mathematical calculations but a whole lot more.

Coding the Function in Swift

Swift’s notation for establishing the existence of a function is a little different than the mathematical one you just saw. In general, the syntax for declaring a Swift function is:

func funcName(paramName : type, ...) -> returnType

Take a look at an example to help clarify the syntax. Figure 4.1 shows the code in the Chapter 4.playground file, along with the function defined on lines 7 through 13. This is the function discussed earlier, but now in a notation that the Swift compiler can understand.

FIGURE 4.1

FIGURE 4.1 Temperature conversion as a Swift function

Start by typing in the following code.

func fahrenheitToCelsius(fahrenheitValue : Double) -> Double {
  var result : Double

  result = (((fahrenheitValue - 32) * 5) / 9)

  return result
}

As you can see on line 7, there is some new syntax to learn. The func keyword is Swift’s way to declare a function. That is followed by the function name (fahrenheitToCelsius), and the independent variable’s name, or parameter name, in parentheses. Notice that the fahrenheitValue parameter’s type is explicitly declared as Double.

Following the parameter are the two characters ->, which denote that this function is returning a value of a type (in this case, a Double type), followed by the open curly brace, which indicates the start of the function.

On line 8, you declare a variable of type Double named result. This will hold the value that will be given back to anyone who calls the function. Notice that it is the same type as the function’s return type declared after the -> on line 7.

The actual mathematical function appears on line 10, with the result of the expression assigned to result, the local variable declared in line 8. Finally on line 12, the result is returned to the caller using the return keyword. Anytime you wish to exit a function and return to the calling party, you use return along with the value being returned.

The Results sidebar doesn’t show anything in the area where the function was typed. That’s because a function by itself doesn’t do anything. It has the potential to perform some useful work, but it must be called by a caller. That’s what you’ll do next.

Exercising the Function

Now it’s time to call on the function you just created. Type in the following two lines of code, and pay attention to the Results sidebar in Figure 4.2.

var outdoorTemperatureInFahrenheit = 88.2
var outdoorTemperatureInCelsius = fahrenheitToCelsius(outdoorTemperatureInFahrenheit)
FIGURE 4.2

FIGURE 4.2 The result of calling the newly created function

On line 15, you’ve declared a new variable, outdoorTemperatureInFahrenheit, and set its value to 88.2 (remember, Swift infers the type in this case as a Double). That value is then passed to the function on line 16, where a new variable, outdoorTemperatureInCelsius, is declared, and its value is captured as the result of the function.

The Results sidebar shows that 31.222222 (repeating decimal) is the result of the function, and indeed, 31.2 degrees Celsius is equivalent to 88.2 degrees Fahrenheit. Neat, isn’t it? You now have a temperature conversion tool right at your fingertips.

Now, here’s a little exercise for you to do on your own: Write the inverse method, celsiusToFahrenheit, using the following formula for that conversion:

086equ01.jpg

Go ahead and code it up yourself, but resist the urge to peek ahead. Don’t look until you’ve written the function, and then check your work against the following code and in Figure 4.3.

func celsiusToFahrenheit(celsiusValue : Double) -> Double {
  var result : Double

  result = (((celsiusValue * 9) / 5) + 32)

  return result
}

outdoorTemperatureInFahrenheit = celsiusToFahrenheit(outdoorTemperatureInCelsius)
FIGURE 4.3

FIGURE 4.3 Declaring the inverse function, celsiusToFahrenheit

The inverse function on lines 18 through 24 simply implements the Celsius to Fahrenheit formula and returns the result. Passing in the Celsius value of 31.22222 on line 26, you can see that the result is the original Fahrenheit value, 88.2.

You’ve just created two functions that do something useful: temperature conversions. Feel free to experiment with other values to see how they change between the two related functions.

More Than Just Numbers

The notion of a function in Swift is more than just the mathematical concept I have discussed. In a broad sense, Swift functions are more flexible and robust in that they can accept more than just one parameter, and even accept types other than numeric ones.

Consider creating a function that takes more than one parameter and returns something other than a Double (Figure 4.4).

FIGURE 4.4

FIGURE 4.4 A multi-parameter function

func buildASentenceUsingSubject(subject : String, verb : String, noun : String) -> String {
  return subject + " " + verb + " " + noun + "!"
}

buildASentenceUsingSubject("Swift", verb: "is", noun: "cool")
buildASentenceUsingSubject("I", verb: "love", noun: "languages")

After typing in lines 28 through 33, examine your work. On line 28, you declared a new function, buildASentence, with not one but three parameters: subject, verb, and noun, all of which are String types. The function also returns a String type as well. On line 29, the concatenation of those three parameters, interspersed with spaces to make the sentence readable, is what is returned.

To demonstrate the utility of the function, it is called twice on lines 32 and 33, resulting in the sentences in the Results sidebar.

If you are familiar with the C language and how parameters are passed to functions, the notation on lines 32 and 33 may appear confusing at first. Swift enforces the notion of named parameters on all but the first parameter of a function. The names that were declared in the function on line 28 (verb and noun) are specified on this line right alongside the actual string values.

Swift enforces the notion of named parameters, which is a legacy of Objective-C. Named parameters bring clarity to your source code by documenting exactly what is being passed. From the code, you can clearly see that the verb and noun are the second and third parameters, respectively.

Feel free to replace the parameters with values of your own liking and view the results interactively.

Parameters Ad Nauseam

Imagine you’re writing the next big banking app for the Mac, and you want to create a way to add some arbitrary number of account balances. Something so mundane can be done a number of ways, but you want to write a Swift function to do the addition. The problem is you don’t know how many accounts will need to be summed at any given time.

Enter Swift’s variable parameter passing notation. It provides you with a way to tell Swift, “I don’t know how many parameters I’ll need to pass to this function, so accept as many as I will give.” Type in the following code, which is shown in action on lines 35 through 48 in Figure 4.5.

FIGURE 4.5

FIGURE 4.5 Variable parameter passing in a function

// Parameters Ad Nauseam
func addMyAccountBalances(balances : Double...) -> Double {
  var result : Double = 0

  for balance in balances {
     result += balance
  }

  return result
}

addMyAccountBalances(77.87)
addMyAccountBalances(10.52, 11.30, 100.60)
addMyAccountBalances(345.12, 1000.80, 233.10, 104.80, 99.90)

This function’s parameter, known as a variadic parameter, can represent an unknown number of parameters.

On line 36, your balances parameter is declared as a Double followed by the ellipsis (...) and returns a Double. The presence of the ellipsis is the clue: It tells Swift to expect one or more parameters of type Double when this function is called.

The function is called three times on lines 46 through 48, each with a different number of bank balances. The totals for each appear in the Results sidebar.

You might be tempted to add additional variadic parameters in a function. Figure 4.6 shows an attempt to extend addMyAccountBalances with a second variadic parameter, but it results in a Swift error.

FIGURE 4.6

FIGURE 4.6 Adding additional variable parameters

This is a no-no, and Swift will quickly shut you down with an error. Only one parameter of a function may contain the ellipsis to indicate a variadic parameter. All other parameters must refer to a single quantity.

Since we’re on the theme of bank accounts, add two more functions: one that will find the largest balance in a given list of balances, and another that will find the smallest balance. Type the following code, which is shown on lines 50 through 75 in Figure 4.7.

FIGURE 4.7

FIGURE 4.7 Functions to find the largest and smallest balance

func findLargestBalance(balances : Double...) -> Double {
  var result : Double = -Double.infinity

  for balance in balances {
     if balance > result {
        result = balance
     }
  }

  return result
}

func findSmallestBalance(balances : Double...) -> Double {
  var result : Double = Double.infinity

  for balance in balances {
     if balance < result {
        result = balance
     }
  }

  return result
}

findLargestBalance(345.12, 1000.80, 233.10, 104.80, 99.90)
findSmallestBalance(345.12, 1000.80, 233.10, 104.80, 99.90)

Both functions iterate through the parameter list to find the largest and smallest balance. Unless you have an account with plus or minus infinity of your favorite currency, these functions will work well. On lines 74 and 75, both functions are tested with the same balances used earlier, and the Results sidebar confirms their correctness.

Functions Fly First Class

One of the powerful features of Swift functions is that they are first-class objects. Sounds pretty fancy, doesn’t it? What that really means is that you can handle a function just like any other value. You can assign a function to a constant, pass a function as a parameter to another function, and even return a function from a function!

To illustrate this idea, consider the act of depositing a check into your bank account, as well as withdrawing an amount. Every Monday, an amount is deposited, and every Friday, another amount is withdrawn. Instead of tying the day directly to the function name of the deposit or withdrawal, use a constant to point to the function for the appropriate day. The code on lines 77 through 94 in Figure 4.8 provides an example.

var account1 = ("State Bank Personal", 1011.10)
var account2 = ("State Bank Business", 24309.63)

func deposit(amount : Double, account : (name : String, balance : Double)) -> (String, Double) {
  let newBalance : Double = account.balance + amount
  return (account.name, newBalance)
}
func withdraw(amount : Double, account : (name : String, balance : Double)) -> (String, Double) {
  var newBalance : Double = account.balance - amount
  return (account.name, newBalance)
}

let mondayTransaction = deposit
let fridayTransaction = withdraw

let mondayBalance = mondayTransaction(300.0, account: account1)
let fridayBalance = fridayTransaction(1200, account: account2)
FIGURE 4.8

FIGURE 4.8 Demonstrating functions as first-class types

For starters, you create two accounts on lines 77 and 78. Each account is a tuple consisting of an account name and balance.

On line 80, a function named deposit is declared, and it takes two parameters: the amount (a Double) and a tuple named account. The tuple has two members: name, which is of type String, and balance, which is a Double that represents the funds in that account. The same tuple type is also declared as the return type.

At line 81, a variable named newBalance is declared, and its value is assigned the sum of the balance member of the account tuple and the amount variable that is passed. The tuple result is constructed on line 82 and returned.

The function on line 85 is named differently (withdraw) but is effectively the same, save for the subtraction that takes place on line 86.

On lines 90 and 91, two new constants are declared and assigned to the functions respectively by name: deposit and withdraw. Since deposits happen on a Monday, the mondayTransaction is assigned the deposit function. Likewise, withdrawals are on Friday, and the fridayTransaction constant is assigned the withdraw function.

Lines 93 and 94 show the results of passing the account1 and account2 tuples to the mondayTransaction and fridayTransaction constants, which are in essence the functions deposit and withdraw. The Results sidebar bears out the result, and you’ve just called the two functions by referring to the constants.

Throw Me a Function, Mister

Just as a function can return an Int, Double, or String, a function can also return another function. Your head starts hurting just thinking about the possibilities, doesn’t it? Actually, it’s not as hard as it sounds. Check out lines 96 through 102 in Figure 4.9.

func chooseTransaction(transaction: String) -> (Double, (String, Double)) -> (String, Double) {
  if transaction == "Deposit" {
     return deposit
  }

  return withdraw
}
FIGURE 4.9

FIGURE 4.9 Returning a function from a function

On line 96, the function chooseTransaction takes a String as a parameter, which it uses to deduce the type of banking transaction. That same function returns a function, which itself takes a Double, and a tuple of String and Double, and returns a tuple of String and Double. Phew!

That’s a mouthful. Let’s take a moment to look at that line more closely and break it down a bit. The line begins with the definition of the function and its sole parameter, transaction, followed by the -> characters indicating the return type:

func chooseTransaction(transaction: String) ->

After that is the return type, which is a function that takes two parameters—the Double, and a tuple of Double and String—as well as the function return characters ->:

(Double, (String, Double)) ->

And finally, the return type of the returned function, a tuple of String and Double.

What functions did you write that meet these criteria? The deposit and withdraw functions, of course! Look at lines 80 and 85. Those two functions are bank transactions that were used earlier. Since they are defined as functions that take two parameters (a Double and a tuple of String and Double) and return a tuple of Double and String, they are appropriate candidates for return values in the chooseTransaction function on line 96.

Back to the chooseTransaction function: On line 97, the transaction parameter, which is a String, is compared against the constant string "Deposit" and if a match is made, the deposit function is returned on line 98; otherwise, the withdraw function is returned on line 101.

OK, so you have a function which itself returns one of two possible functions. How do you use it? Do you capture the function in another variable and call it?

Actually, there are two ways this can be done (Figure 4.10).

// option 1: capture the function in a constant and call it
let myTransaction = chooseTransaction("Deposit")
myTransaction(225.33, account2)

// option 2: call the function result directly
chooseTransaction("Withdraw")(63.17, account1)
FIGURE 4.10

FIGURE 4.10 Calling the returned function in two different ways

On line 105 you can see that the returned function for making deposits is captured in the constant myTransaction, which is then called on line 106 with account2 increasing its amount by $225.33.

The alternate style is on line 109. There, the chooseTransaction function is being called to gain access to the withdraw function. Instead of assigning the result to a constant, however, the returned function is immediately pressed into service with the parameters 63.17 and the first account, account1. The results are the same in the Results sidebar: The withdraw function is called and the balance is adjusted.

A Function in a Function in a...

If functions returned by functions and assigned to constants isn’t enough of an enigma for you, how about declaring a function inside another function? Yes, such a thing exists. They’re known as nested functions.

Nested functions are useful when you want to isolate, or hide, specific functionality that doesn’t need to be exposed to outer layers. Take, for instance, the code in Figure 4.11.

// nested function example
func bankVault(passcode : String) -> String {
  func openBankVault(_: Void) -> String {
     return "Vault opened"
  }
  func closeBankVault() -> String {
     return "Vault closed"
  }
  if passcode == "secret" {
     return openBankVault()
  }
  else {
     return closeBankVault()
  }
}

print(bankVault("wrongsecret"))
print(bankVault("secret"))
FIGURE 4.11

FIGURE 4.11 Nested functions in action

On line 112, a new function, bankVault, is defined. It takes a single parameter, passcode, which is a String, and returns a String.

Lines 113 and 116 define two functions inside the bankVault function: openBankVault and closeBankVault. Both of these functions take no parameter and return a String.

On line 119, the passcode parameter is compared with the string "secret" and if a match is made, the bank vault is opened by calling the openBankVault function. Otherwise, the bank vault remains closed.

Lines 127 and 128 show the result of calling the bankVault method with an incorrect and correct passcode. What’s important to realize is that the openBankVault and closeBankVault functions are “enclosed” by the bankVault function, and are not known outside of that function.

If you were to attempt to call either openBankVault or closeBankVault outside of the bankVault function, you would get an error. That’s because those functions are not in scope. They are, in effect, hidden by the bankVault function and are unable to be called from the outside. Figure 4.12 illustrates an attempt to call one of these nested functions.

FIGURE 4.12

FIGURE 4.12 The result of attempting to call a nested function from a different scope

In general, the obvious benefit of nesting functions within functions is that it prevents the unnecessary exposing of functionality. In Figure 4.12, the bankVault function is the sole gateway to opening and closing the vault, and the functions that perform the work are isolated within that function. Always consider this when designing functions that are intended to work together.

Default Parameters

As you’ve just seen, Swift functions provide a rich area for utility and experimentation. A lot can be done with functions and their parameters to model real-world problems. Functions provide an interesting feature known as default parameter values, which allow you to declare functions that have parameters containing a “prefilled” value.

Let’s say you want to create a function that writes checks. Your function would take two parameters: a payee (the person or business to whom the check is written) and the amount. Of course, in the real world, you always want to know these two pieces of information, but for now, think of a function that would assume a default payee and amount in the event the information wasn’t passed.

Figure 4.13 shows such a function on lines 130 through 132. The writeCheckTo function takes two String parameters, the payee and amount, and returns a String that is simply a sentence describing how the check is written.

func writeCheckTo(payee : String = "Unknown", amount : String = "10.00") -> String {
  return "Check payable to " + payee + " for $" + amount
}

writeCheckTo()
writeCheckTo("Donna Soileau")
writeCheckTo("John Miller", amount : "45.00")
FIGURE 4.13

FIGURE 4.13 Using default parameters in a function

Take note of the declaration of the function on line 130:

func writeCheckTo(payee : String = "Unknown", amount : String = "10.00") -> String

What you haven’t seen before now is the assignment of the parameters to actual values (in this case, payee is being set to "Unknown" by default and amount is being set to "10.00"). This is how you can write a function to take default parameters—simply assign the parameter name to a value!

So how do you call this function? Lines 134 through 136 show three different ways:

  • Line 134 passes no parameters when calling the function.
  • Line 135 passes a single parameter.
  • Line 136 passes both parameters, with the second parameter following its parameter name amount.

In the case where no parameters are passed, the default values are used to construct the returned String. In the other two cases, the passed parameter values are used in place of the default values, and you can view the results of the calls in the Results sidebar.

Recall that Swift enforces the requirement that the parameter name must be passed for all but the first parameter. On line 135, only one parameter is used, so the name is not passed:

writeCheckTo("Donna Soileau")

On line 136, two parameter names are used, and the parameter name is specified prior to the amount string:

writeCheckTo("John Miller", amount : "45.00")

Default parameters give you the flexibility of using a known value instead of taking the extra effort to pass it explicitly. They’re not necessarily applicable for every function out there, but they do come in handy at times.

What’s in a Name?

As Swift functions go, declaring them is easy, as you’ve seen. In some cases, however, what really composes the function name is more than just the text following the keyword func.

As I touched on earlier, each parameter in a Swift function has the parameter name preceding the parameter. This gives additional clarity and description to a function name. Up to this point, you’ve been told that it must be passed when calling the function. Although it is good practice, it is not entirely necessary. When declaring a function, an implicit external parameter name can be notated with an underscore preceding the parameter name. Consider another check writing function in Figure 4.14, lines 138 through 140.

func writeCheckFrom(payer : String, _ payee : String, _ amount : Double) -> String {
  return "Check payable from \(payer) to \(payee) for $\(amount)"
}

writeCheckFrom("Dave Johnson", "Coz Fontenot", 1_000.0)
FIGURE 4.14

FIGURE 4.14 A function with an implicit external parameter name

This function is different from the earlier check writing function on lines 130 through 132 in two ways:

  • An underscore and a space precede the parameters named payee and amount
  • There are no default parameters

On line 142, the new writeCheckFrom function is called with three parameters: two String values and a Double value. From the name of the function, its purpose is clearly to write a check. When writing a check, you need to know several things: who the check is being written for, who is writing the check, and the amount the check is for. A good guess is that the Double parameter is the amount, which is a number. But without actually looking at the function declaration itself, how would you know what the two String parameters actually mean? Even if you were to deduce that they are the payer and payee, how do you know which is which, and in which order to pass the parameters?

Swift’s default behavior of insisting on the use of parameter names solves this problem and makes the intent of your code easier to understand; it makes very clear to anyone reading the calling function what the intention is and the purpose of each parameter. Figure 4.15 illustrates this.

func writeBetterCheckFrom(payer : String, payee : String, amount : Double) -> String {
  return "Check payable from \(payer) to \(payee) for $\(amount)"
}

writeBetterCheckFrom("Fred Charlie", payee : "Ryan Hanks", amount : 1350.0)
FIGURE 4.15

FIGURE 4.15 A function called with parameter names

On line 144, you declare a function, writeBetterCheckFrom, which takes the same number of parameters as the function on line 138. However, each of the parameters in the new function omits the underscore.

The extra bit of typing pays off when the writeBetterCheckFrom function is called. Looking at that line of code alone, the order of the parameters and what they indicate is clear: Write a check from Fred Charlie to Ryan Hanks for a total of $1350.

When It’s Good Enough

Parameter names bring clarity to functions, as you’ve just seen. In addition, Swift allows external parameter names to decorate a function declaration. This can be useful if you want to bring additional clarity to your function.

Line 150 of Figure 4.16 shows this in action. The new method, writeBestCheck has dropped the From in the name. Instead, it has moved to the first parameter as an external parameter name. Other external parameter names in this function declaration are to and total.

FIGURE 4.16

FIGURE 4.16 Using the external parameter name syntax

On line 154, the parameter names are used as external parameter names to call the function, and the use of those names clearly shows what the function’s purpose and parameter order is: a check written from Bart Stewart to Alan Lafleur for a total of $101. Note that when using external parameter names, the first parameter also requires the parameter name to be passed. This is different from what you saw earlier when your earlier functions weren’t using external parameter names.

func writeBestCheck(from payer : String, to payee : String, total amount : Double) -> String {
  return "Check payable from \(payer) to \(payee) for $\(amount)"
}

writeBestCheck(from: "Bart Stewart", to: "Alan Lafleur", total: 101.0)

To Use or Not to Use?

Parameter names bring clarity to functions, but they also require more typing on the part of the coder who uses your functions. Since they are optional parts of a function’s declaration, when should you use them?

In general, if the function in question can benefit from the additional clarity of having parameter names provided for each parameter, by all means use them. The check writing example is such a case. Avoid parameter ambiguity in the cases where it might exist. On the other hand, if you’re creating a function that just adds two numbers (see lines 156 through 160 in Figure 4.17), parameter names add little to nothing of value for the caller. You can just use the underscore (recall implicit external parameter names) and avoid passing the parameter name altogether.

func addTwoNumbers(number1 : Double, _ number2 : Double) -> Double {
  return number1 + number2
}

addTwoNumbers(33.1, 12.2)
FIGURE 4.17

FIGURE 4.17 When parameter names are not necessary

Don’t Change My Parameters!

Functions are prohibited from changing the values of parameters passed to them, because parameters are passed as constants and not variables. Consider the function cashCheck on lines 162 through 169 in Figure 4.18.

func cashCheck(from : String, to : String, total : Double) -> String {
  if to == "Cash" {
    to = from
  }
  return "Check payable from \(from) to \(to) for $\(total) has been cashed"
}

cashCheck("Jason Guillory", to: "Cash", total: 103.00)
FIGURE 4.18

FIGURE 4.18 Assigning a value to a parameter results in an error.

The function takes the same parameters as your earlier check writing function: who the check is from, who the check is to, and the total. On line 163, the to variable is checked for the value "Cash" and if it is equal, it is reassigned the contents of the variable from. The rationale here is that if you are writing a check to “Cash,” you’re essentially writing it to yourself.

Notice the error: Cannot assign to value: 'to' is a 'let' constant. Swift is saying that the parameter to is a constant, and since constants cannot change their values once assigned, this is prohibited and results in an error.

To get around this error, you could create a temporary variable, as done in Figure 4.19. Here, a new variable named otherTo is declared on line 163 and assigned to the to variable, and then possibly to the from variable on line 165, assuming the condition on line 164 is met. This is clearly acceptable and works fine for your purposes, but Swift gives you a better way.

FIGURE 4.19

FIGURE 4.19 A potential workaround to the parameter change problem

With a var declaration on a parameter, you can tell Swift that the parameter is intended to be variable and can change within the function. All you need to do is add the keyword before the parameter name (or external parameter name in case you have one of those). Figure 4.20 shows a second function, cashBetterCheck, which declares the to parameter as a variable parameter. Now the code inside the function can modify the to variable without receiving an error from Swift, and the output is identical to the workaround function above it.

func cashBetterCheck(from : String, var to : String, total : Double) -> String {
  if to == "Cash" {
     to = from
  }
    return "Check payable from \(from) to \(to) for $\(total) has been cashed"
}

cashBetterCheck("Ray Daigle", to: "Cash", total: 103.00)
FIGURE 4.20

FIGURE 4.20 Using variable parameters to allow modifications

The Ins and Outs

As you’ve just seen, a function can be declared to modify the contents of one or more of its passed variables. The modification happens inside the function itself, and the change is not reflected back to the caller.

Sometimes having a function change the value of a passed parameter so that its new value is reflected back to the caller is desirable. For example, in the cashBetterCheck function on lines 172 through 177, having the caller know that the to variable has changed to a new value would be advantageous. Right now, that function’s modification of the variable is not reflected back to the caller. Let’s see how to do this in Figure 4.21 using Swift’s inout keyword.

func cashBestCheck(from : String, inout to : String, total : Double) -> String {
  if to == "Cash" {
     to = from
  }
  return "Check payable from \(from) to \(to) for $\(total) has been cashed"
}

var payer = "James Perry"
var payee = "Cash"
print(payee)
cashBestCheck(payer, to: &payee, total: 103.00)

print(payee)
FIGURE 4.21

FIGURE 4.21 Using the inout keyword to establish a modifiable parameter

Lines 181 through 186 define the cashBestCheck function, which is virtually identical to the cashBetterCheck function on line 172, except the second parameter to is no longer a variable parameter—the var keyword has been replaced with the inout keyword. This new keyword tells Swift that the parameter’s value can be expected to change in the function and that the change should be reflected back to the caller. With that exception, everything else is the same between the cashBetterCheck and cashBestCheck functions.

On lines 188 and 189, two variables are declared: payer and payee, with both being assigned String values. This is done because inout parameters must be passed a variable. A constant value will not work, because constants cannot be modified.

On line 190, the payee variable is printed, and the Results sidebar for that line clearly shows the variable’s contents as "Cash". This is to make clear that the variable is set to its original value on line 189.

On line 191, you call the cashBestCheck function. Unlike the call to cashBetterCheck on line 179, you are passing variables instead of constants for the to and from parameters. More so, for the second parameter (payee), we are prepending the ampersand character (&) to the variable name. This is a direct result of declaring the parameter in cashBestCheck as an inout parameter. You are in essence telling Swift that this variable is an inout variable and that you expect it to be modified once control is returned from the called function.

On line 193, the payee variable is again printed. This time, the contents of that variable do not match what was printed on line 190 earlier. Instead, payee is now set to the value "James Perry", which is a direct result of the assignment in the cashBestCheck function on line 183.

Peachpit Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from Peachpit and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about Peachpit products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites; develop new products and services; conduct educational research; and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email ask@peachpit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by Adobe Press. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.peachpit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020