Swift Function

Swift Functions are self-contained chunks of code that perform a specific task. You give a function a name that identifies what it does, and this name is used to “call” the function to perform its task when needed.

We’ll be covering the following concepts in this tutorial.

  1. Named and Unnamed parameters
  2. Default parameter value
  3. Multiple return types
  4. Inout parameters
  5. Variadic parameters
  6. Nested functions
  7. Functions as types, parameters, and return type

Let’s open up our Playground in XCode and dive right in!

Defining and Calling Swift Function

To define a swift function, we need to start with the keyword func followed by the name of the function as shown below.

func helloFunction() {
  print("Hello Swift Functions)
}

Swift Functions with parameters and return types

Let’s define a swift function with parameters and see what it looks like.

func display(websiteName w: String, withTutorial t: String) {
   print(w + " " + t)
}

The code snippet inside the parenthesis can look intimidating at first. Let’s observe it closely.

The parameters inside the above function consist of two parts. An external parameter followed by an internal parameter. Such type of parameters consisting of two labels is known as named parameters.

  1. The type of parameter follows after the colon :
  2. websiteName and withTutorial are the external parameters and shall be only used when calling the function. External parameters are also known as argument labels.
  3. w and t are the internal parameters and would be used inside the body of the function. Internal parameters are also known as local parameters.

The above function is called in the following way.

display(websiteName: "balututorial.com", withTutorial: "Functions In Swift")

The swift function named parameters is useful in the essence that they indicate the purpose of the parameters in the functions through argument labels thereby reflecting what the function does in a clear way.

Another way of defining a function is given below

func appendStrings(a : String, b: String) {
    print(a + " " + b)
}

appendStrings(a: "Hello", b:"Swift")

In the above code, we haven’t explicitly set the external and internal parameters. Swift considers them as both in the above case. To omit the external parameter(argument label) explicitly, we need to add an underscore _.

Following code, snippet demonstrates an example where the first parameter is unnamed.

func appendString(_ a: String, with b: String) {
  print(a + " " + b)   
}

appendString("Hello", with: "Swift") 

[quote]We cannot change the parameter value inside a function (At least not with the above approach).[/quote]

Next, let’s create a function with a return type.

func sumOfInteger(_ a: Int, _ b:Int) -> Int {
  return a + b
}
print(sumOfInteger(2,3))

To set a return type we’ve added the operator -> followed by the data type being returned. A default value for any parameter in a function can be assigned after the parameter’s type. If a default value is defined, we can omit that parameter when calling the function.

Let’s create a function which has a default value set for a parameter as shown below

func sumOfInteger(_ a:Int, _ b:Int = 2) -> Int {

   return a + b
}
sumOfInteger(sum(5))     //prints 7
sumOfInteger(sum(5, 3))  //prints 8

Swift Function inout parameters

inout parameters used to change the value of a parameter such that the new value is persistent even after the function call is over we define the parameter as an inout. A code snippet below demonstrates a function with such parameter.

var i = 3
print(i) //prints 3

func increment(_ i: inout Int, by x: Int) -> Int {
    i = i + x

    return i
}
increment(&i, by: 3)

print(i) //prints 6

Constants can’t be passed as swift function inout parameters.

[quote]inout parameters are similar to passing by reference in C.[/quote]

Swift Function variadic parameters

Swift function variadic parameter accepts zero or more values of a specified type. Only one variadic parameter is allowed per function. A variadic parameter is denoted by  after the type of the parameter as shown below.

func makeSentence( words: String...) -> String {
    var sentence = ""
    for word in words {
     sentence = sentence + " " + word
    }

    return sentence
}

makeSentence(words: "Function","having", "Variadic parameters","Add as many strings here you want", "Can use one variadic parameter per func","Make full use")

Swift Function returning multiple values

We can use a tuple type as the return type for a function to return multiple values as one compound value as shown below.

func returnSentenceAndWordCount(_ strings: String...) -> (sentence: String, wordCount: Int) {
    var sentence = ""
    for s in strings {
        sentence = sentence + " " + s
    }

    return (sentence, strings.count)
}

let data = returnSentenceAndWordCount("Function","returns a tuple", "containing", "sentence and number of strings and word count")
                                      
print(data.sentence + "\n\(data.wordCount)")

The tuple members are accessed using the dot operator on the returned type.

Nested Functions in Swift

Swift allows us to define a function within a function as shown below.

func sayHello(to name: String) {
    let s = "Hello " + name
    func printString() {
        print(s)
    }
}
sayHello(to: "BaluTutorial")  //prints Hello BaluTutorial

In the above code, the constants are available to the nested function.

Swift Functions as types, parameters and return types

The parameter types and return types of functions can make up a custom independent data type that can be used smartly in Swift. Besides, functions in Swift allows passing another function as a parameter or return type too. We’ll be implementing each of these below. Let’s start by creating two basic functions as shown below.

//Function to calculate square of an integer.

func square(_ num :Int)->Int {

     return num * num
}
square(4) // returns 16

//Function to calculate cube of an integer.

func cube(_ num :Int)->Int {

    return num * num * num
}
cube(4) // returns 64

We can assign a function to a variable/constant as shown below.

var exponentialFunction = square

exponentialFunction is defined as a variable which is of the type of a function that takes an Int parameter and returns an Int parameter. We can now call the variable exponentialFunction as shown in the below code snippet.

exponentialFunction(4)            //This would work the same way as square(4)

square(exponentialFunction(5))    //This would return 625

exponentialFunction(exponentialFunction(5))   //Same as above

We can change the type of exponentialFunction to the function cube as shown below.

exponentialFunction = cube(_:)
square(exponentialFunction(5))     // square of cube of 5. returns 15625

Let’s create a function that accepts the square and cube of the above function as parameters.

var integers = [1,2,3,4,5]

func sumOfExponentialsOf(array a: [Int], with function: (Int)->Int)->Int {
    var result = 0
    for x in a {
        result = result + function(x)
    }

    return result   
}

The above function calculates the sum of function returned values for all array elements. Swift is smart enough to infer the type of variable/constant from the value.

The second parameter accepts a type (Int)->Int which is the same type as for exponentialFunction.

We’ll use the above function to calculate the sum of squares and sum of cubes of all array elements as shown below.

exponentialFunction = square(_:)

//sum of squares of all array elements
sumOfExponentialsOf(array: integers, with: exponentialFunction) // returns 55
exponentialFunction = cube(_:)

//sum of cubes of all array elements
sumOfExponentialsOf(array: integers, with: exponentialFunction) // returns 225

Lastly, it’s possible for a function to return another function. Let’s create a function that returns either the square or cube function based on a condition.

func chooseComputation(isSquared b : Bool) -> (Int)->Int {
    func square(_ num :Int)->Int {

        return num * num
    }
    
    func cube(_ num :Int)->Int {

        return num * num * num
    }
    
    if b {

        return square
    } else{

        return cube
    }
}

var result = chooseComputation(isSquared: true)
result(2) //returns 4

result = chooseComputation(isSquared: false)
result(2) //returns 8

The chooseComputation function consists of two functions with the same type as of return.

Based on the boolean value the chooseComputation function returns a reference to either of the nested functions which are then referenced from the result variable.