Some Additional Functionalities Of Swift – Part 2

Functions

In Swift, every function has a type that contains the function’s parameter types and return type. This type can be used like any other type in Swift, and this makes passing functions as parameters to other functions and returning functions from functions easier.
Functions can also be written within other functions to encapsulate useful functionality within a nested function scope.

Variadic Parameters

Variadic parameters indicate that the number of input values of a specified type passed to the parameter can vary. The variadic parameter can accept zero and/or more parameters of a certain type, and is indicated by adding three period characters (…) immediately following the parameter‘s type name.

The values passed to a variadic parameter appear as an array of the specified type in the function’s body.

In the example below, the function calculates the arithmetic mean, or average, for a list of numbers of any length:

func arithmeticMean(numbers: Double...) -> Double {
   var total: Double = 0
   for number in numbers {
     total += number
   }
   return (total / Double(numbers.count))
}

One variadic parameter is allowed per function. The variadic parameter must always be the last parameter in the list, to ensure clarity when calling the function with multiple parameters.
For a function with one or more parameters containing default values, as well as a variadic parameter, the variadic parameter is added at the very end of the list, following all defaulted parameters.

In-Out Parameters

A variable parameter is changeable only within the function. The in-out parameter is used as an alternative to the variable parameter in instances in which you want a change to continue after the function call ends.

The inout keyword is placed at the beginning of the parameter‘s definition. Its value is passed in to the function, where it is modified. It’s then passed back out of the function, where it replaces the original value.

This example swaps out two Integer values.

func swapInts(inout a: Int, inout b: Int) {
   let tempA = a
   a = b
   b = tempA
}

An in-out parameter cannot be assigned a default value. A variadic parameter cannot be marked as inout. A parameter that is marked as inout cannot also be marked as var or let.
An ampersand (&) that is inserted directly before a variable‘s name when it’s passed as an argument to an inout parameter, indicates that the variable can be modified by the function:

var someInt = 3
var anotherInt = 107
swapInts(&someInt, &anotherInt)

The in-out parameter presents an alternative method when a function is desired to have an effect outside of the scope of its function body.

Function Types

Every function has a specific function type that consists of the function’s parameter types and return type. Here’s an example:

func addInts(a: Int, b: Int) -> Int {
 return a + b
}
func multiplyInts(a: Int, b: Int) -> Int {
 return a * b
}

This example defines two simple mathematical functions called addInts and multiplyInts, which take two Int values, which return an Int value.
For both of these functions, the type is (Int, Int) -> Int. This can be interpreted as
“A function type that has two parameters, both of type Int; and that returns a value of type Int.”

Here’s another example. This one shows a function with no parameters or return value:

func printHelloWorld() {
   print("Hello, world")
}

The type of this function is () -> Void, which translates into “a function that has no parameters, and returns Void.”

Using Function Types

Function types are used in the same way as any other Swift types.
For example, define a constant or a variable to be of a function type. Then assign an appropriate function to that variable:

var mathFunction: (Int, Int) -> Int = addInts

You can now call the assigned function using its name, mathFunction.

print("Result: \(mathFunction(2, 3))")

A different function with the same type can be assigned to the same variable, in the same way as for non-function types.

Function Types as Parameter Types

A function type, such as (Int, Int) -> Int, can act as a parameter type for a different function, allowing for leaving some aspects of a function’s implementation for the function’s caller to provide calling the function.
The following example defines a function called printResult, which takes another function as its parameter and calls it as it’s implemented:

func printResult(mathFunc: (Int, Int) -> Int, a: Int, b: Int) {
   print("Result: \(mathFunc(a, b))")
}
printResult(addInts, 3, 5) 

It doesn’t matter what the called function’s implementation actually does – it matters only that the function is of the correct type.

Function Types as Return Types

A function type may be used as another function’s return type, by writing a complete function type immediately following the return arrow (->) in the returning function.

func plus(input: Int) -> Int {
   return input + 1
}
func minus(input: Int) -> Int {
   return input - 1
}
func chooseFunc(flag: Bool) -> (Int) -> Int {
   if(flag) {
     return plus
   }
   else {
     return minus
   }
}

In the above example, the chooseFunc function returns another function of type (Int) -> Int, based on the value of its flag parameter.

Nested Functions

You also have the option of defining functions inside the bodies of other functions. These are called nested functions.

By default, a nested function is hidden from the outside world. It can still be called and used by its enclosing function. An enclosing function can also return one of its nested functions, thus allowing the nested function to be used in another scope.

From the previous lesson, the function chooseFunc can be rewritten to use and return nested functions:

func chooseFunc(flag: Bool) -> (Int) -> Int {
   func plus(input: Int) -> Int { return input + 1 }
   func minus(input: Int) -> Int { return input - 1 }
   if(flag) {
     return plus
   }
   else {
     return minus
   }
}
Advertisements
Some Additional Functionalities Of Swift – Part 2