Lesson 38Functions

Function Types

Functions as Values

In Swift, functions are first-class citizens. They have types and can be stored in variables, passed as parameters, or returned from other functions!

Function Type Syntax

(ParameterTypes) -> ReturnType

Examples

(Int, Int) -> Int

Takes two Ints, returns Int

(String) -> String

Takes String, returns String

() -> Void

No params, no return

() -> Int

No params, returns Int

What You Can Do

  • Store functions in variables
  • Pass functions as parameters
  • Return functions from functions
  • Store functions in arrays/dictionaries

Type Alias

typealias MathFunc = (Int, Int) -> Int

Creates a readable name for complex function types!

main.swift
// FUNCTION TYPES
// Every function has a type based on its parameters and return

// This function's type is: (Int, Int) -> Int
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}

// This function's type is: () -> Void (or () -> ())
func sayHello() {
    print("Hello!")
}

// This function's type is: (String) -> String
func greet(_ name: String) -> String {
    return "Hello, \(name)!"
}

// STORING FUNCTIONS IN VARIABLES
var mathOperation: (Int, Int) -> Int = add
print(mathOperation(5, 3))  // 8

// Can reassign to any function with same type
func multiply(_ a: Int, _ b: Int) -> Int {
    return a * b
}

mathOperation = multiply
print(mathOperation(5, 3))  // 15

// FUNCTIONS AS PARAMETERS
func calculate(_ a: Int, _ b: Int,
               using operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}

print(calculate(10, 5, using: add))       // 15
print(calculate(10, 5, using: multiply))  // 50

// FUNCTIONS AS RETURN VALUES
func getOperation(for symbol: String) -> (Int, Int) -> Int {
    switch symbol {
    case "+": return add
    case "*": return multiply
    default: return add
    }
}

let op = getOperation(for: "+")
print(op(3, 4))  // 7

// PRACTICAL EXAMPLE: Sorting
let numbers = [5, 2, 8, 1, 9]

func ascending(_ a: Int, _ b: Int) -> Bool {
    return a < b
}

func descending(_ a: Int, _ b: Int) -> Bool {
    return a > b
}

print(numbers.sorted(by: ascending))   // [1, 2, 5, 8, 9]
print(numbers.sorted(by: descending))  // [9, 8, 5, 2, 1]

// ARRAY OF FUNCTIONS
let operations: [(Int, Int) -> Int] = [add, multiply]

for operation in operations {
    print(operation(4, 2))
}
// 6 (4+2)
// 8 (4*2)

// TYPE ALIAS for clarity
typealias MathFunction = (Int, Int) -> Int

var myFunc: MathFunction = add
func applyTwice(_ f: MathFunction, to a: Int, and b: Int) -> Int {
    return f(f(a, b), b)
}

Try It Yourself!

Create a function that takes two numbers and a math operation function, applies it, and prints the result!