Advanced parameter handling
Function parameters are constants by default, which means they can’t be modified. To illustrate this point, consider the following code:
func incrementAndPrint(_ value: Int) { value += 1
print(value)
}
This results in an error:
Left side of mutating operator isn't mutable: 'value' is a 'let' constant
The parameter value is the equivalent of a constant declared with let. Therefore, when the function attempts to increment it, the compiler emits an error.
An important point to note is that Swift copies the value before passing it to the function, a behavior known as pass-by-value.
Note: Pass-by-value and making copies is the standard behavior for all of the types you’ve seen so far in this book. You’ll see another way for things to be passed into functions in Chapter 14, “Classes”.
Usually you want this behavior. Ideally, a function doesn’t alter its parameters. If it did, then you couldn’t be sure of the parameters’ values and you might make incorrect assumptions in your code, leading to the wrong data.
Sometimes you do want to let a function change a parameter directly, a behavior known as copy-in copy-out or call by value result. You do it like so:
func incrementAndPrint(_ value: inout Int) { value += 1
print(value)
}
The inout keyword before the parameter type indicates that this parameter should be copied in, that local copy used within the function, and then copied back out when the function returns.
You need to make a slight tweak to the function call to complete this example. Add an ampersand (&) before the argument, which makes it clear at the call site that you are using copy-in copy-out:
var value = 5 incrementAndPrint(&value) print(value)
Now the function can change the value however it wishes.
This example will print the following:
6
6
The function successfully increments value, which retains its modified data after the function finishes. The value goes in to the function and then comes back out again, thus the keyword inout.
Under certain conditions, the compiler can simplify copy-in copy-out to what is called pass-by-reference. The argument value isn’t copied into the parameter. Instead, the parameter will just hold a reference to the memory of original value. This optimization satisfies all of the requirements of copy-in copy-out while removing need to actually make copies.