When declaring a function in Swift, we will add any modifier in front of parameters normally:
func incrementor(variable: Int) -> Int {
return variable + 1
}
This function accepts an Int
input, adds a 1, then returns a new Int
value 1 greater than the input one. Nothing special, it is a simple "+1" adder.
If you know the increment operator ++
, you may remember this operator means "plus 1 and assign back". So is it OK to write this code instead of above?
This is wrong code
func incrementor(variable: Int) -> Int { return ++variable }
Oops..compile error. The similar code would be compiled in C and Objective-C, so why not in Swift? Swift is a language "hates" mutability. The default input parameter is a constant value in fact, which means an implicit let
is used here. The equivalent code of above would be
This is wrong code
func incrementor(let variable: Int) -> Int { return ++variable }
Of course, a let
constant cannot be assigned again. To make the snippet gets compiled, we can modify the let
to var
. It indicates the input is not a constant anymore, so it can be re-assigned in the method:
func incrementor(var variable: Int) -> Int {
variable += 1
return variable
}
Cheers, the "+1" adder works again:
var luckyNumber = 7
let newNumber = incrementor(luckyNumber)
// newNumber = 8
print(luckyNumber)
// luckyNumber is still 7
Although when we change the parameter to follow var
, the method is returning the correct value for us. However, from Swift 2.2, we would find some warnings. Adding var
to a parameter is already marked as deprecated. Now, we can only assign the parameter to a variable inside the function, and then manipulate the new created value:
func incrementor2(variable: Int) -> Int {
var num = variable
num += 1
return num
}
Comparing with the way before Swift 2.2, the new code snippet points out what happened explicitly. It is much better than the old way: everything is expected and there is no magic in the code.
Sometimes, we even wish change the input value just in place in the method. inout
is for it:
func incrementor(inout variable: Int) {
variable += 1
}
As a side effect, since the variable
is increased itself, we do not have to return it anymore. The calling is changed also, we need to add a &
:
var luckyNumber = 7
incrementor(&luckyNumber)
print(luckyNumber)
// luckyNumber = 8
There is a limitation when passing parameters with modifier. All parameters in different level of methods should keep the same. For example, if we want to expand the code above to a general "+N" adder, one way is by nested function like this:
func makeIncrementor(addNumber: Int) -> ((inout Int) -> Void) {
func incrementor(inout variable: Int) -> Void {
variable += addNumber;
}
return incrementor;
}
The outer makeIncrementor
should mark inout
in the return value explicitly as well to match the inner definition, or it will not compile at all.