Functions as types in Swift - Time & Space Complexity
When we use functions as types, we want to know how calling these functions affects how long our program takes to run.
We ask: How does the time grow when we call functions stored as variables or passed around?
Analyze the time complexity of the following code snippet.
func applyTwice(_ f: (Int) -> Int, to x: Int) -> Int {
return f(f(x))
}
func addOne(_ n: Int) -> Int {
return n + 1
}
let result = applyTwice(addOne, to: 5)
print(result) // 7
This code calls a function passed as a parameter two times in a row on a number.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Calling the function
ftwice. - How many times: Exactly two times, no loops or recursion.
Each time we call applyTwice, the function f runs two times regardless of the input number.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 2 calls to f |
| 100 | 2 calls to f |
| 1000 | 2 calls to f |
Pattern observation: The number of calls stays the same no matter how big the input number is.
Time Complexity: O(1)
This means the time to run does not grow with the input size; it stays constant.
[X] Wrong: "Calling a function twice means the time doubles with input size."
[OK] Correct: The number of calls is fixed at two, so time does not grow with input size.
Understanding how function calls affect time helps you explain code efficiency clearly and confidently.
What if we changed applyTwice to call the function f n times instead of two? How would the time complexity change?
Practice
Solution
Step 1: Understand the concept of types in Swift
In Swift, types define what kind of values variables can hold.Step 2: Apply this to functions
Functions have types too, meaning they can be assigned to variables, passed as arguments, or returned from other functions.Final Answer:
Functions can be stored in variables and passed around like values. -> Option AQuick Check:
Functions as values = Functions can be stored in variables and passed around like values. [OK]
- Thinking functions can't be assigned to variables
- Assuming functions must return Int
- Believing functions can't take parameters
Solution
Step 1: Recall Swift function type syntax
Function types are written as (ParameterTypes) -> ReturnType, with parameters separated by commas.Step 2: Check each option
var operation: (Int, Int) -> Int correctly uses (Int, Int) -> Int. Others have syntax errors or missing arrows.Final Answer:
var operation: (Int, Int) -> Int -> Option DQuick Check:
Correct function type syntax = var operation: (Int, Int) -> Int [OK]
- Omitting commas between parameter types
- Missing arrow '->' in function type
- Incorrect parameter grouping
func add(_ a: Int, _ b: Int) -> Int { a + b }
var mathOperation: (Int, Int) -> Int = add
print(mathOperation(3, 4))Solution
Step 1: Understand function assignment
The function 'add' matches the type (Int, Int) -> Int, so it can be assigned to 'mathOperation'.Step 2: Evaluate the function call
Calling mathOperation(3, 4) calls add(3, 4), which returns 3 + 4 = 7.Final Answer:
7 -> Option AQuick Check:
Function call result = 7 [OK]
- Expecting string concatenation instead of addition
- Thinking function assignment causes error
- Confusing function call syntax
var multiply: (Int, Int) -> Int
multiply = { a, b in a * b }
print(multiply(2))Solution
Step 1: Check closure assignment
The closure { a, b in a * b } correctly matches (Int, Int) -> Int type.Step 2: Check function call
Calling multiply(2) provides only one argument, but multiply expects two Ints.Final Answer:
Calling multiply with wrong number of arguments -> Option CQuick Check:
Argument count mismatch = Calling multiply with wrong number of arguments [OK]
- Assuming closure needs explicit return
- Ignoring argument count in function call
- Thinking variable is uninitialized
(Int) -> (Int) -> Int, what does this type represent in Swift?Solution
Step 1: Analyze the nested function type
The type (Int) -> (Int) -> Int means the function takes one Int and returns another function.Step 2: Understand the returned function
The returned function itself takes an Int and returns an Int.Final Answer:
A function that takes an Int and returns another function that takes an Int and returns an Int. -> Option BQuick Check:
Curried function type = A function that takes an Int and returns another function that takes an Int and returns an Int. [OK]
- Confusing nested function types with multiple parameters
- Assuming it returns an array
- Ignoring that return type can be a function
Ready to prove it?
Pass the test and this pattern moves unknown
