Why functions are first-class in Swift - Performance Analysis
We want to understand how using functions as values affects the cost of running Swift code.
Specifically, how does calling or passing functions change the number of steps the program takes?
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 defines a function that takes another function and applies it twice to a number.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Calling the passed-in function twice.
- How many times: Exactly two calls, no loops or recursion.
Since the function calls happen a fixed number of times, the steps do not grow with input size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 2 function calls |
| 100 | 2 function calls |
| 1000 | 2 function calls |
Pattern observation: The number of operations stays the same no matter how big the input is.
Time Complexity: O(1)
This means the time to run does not increase as the input number gets bigger.
[X] Wrong: "Passing functions always makes the program slower as input grows."
[OK] Correct: Here, the function calls happen a fixed number of times, so the input size does not affect speed.
Understanding how functions as values work helps you explain code clearly and reason about performance in real projects.
"What if the function was applied inside a loop running n times? How would the time complexity change?"
Practice
Solution
Step 1: Understand what first-class means in Swift
First-class means functions can be treated like any other value, such as assigned to variables or passed around.Step 2: Identify the correct property of functions in Swift
Swift allows functions to be stored in variables and passed as arguments, which matches the definition of first-class citizens.Final Answer:
Because functions can be assigned to variables and passed as arguments -> Option AQuick Check:
Functions as values = Because functions can be assigned to variables and passed as arguments [OK]
- Thinking functions cannot be passed as arguments
- Believing functions must be global only
- Assuming functions cannot return values
Solution
Step 1: Recall Swift syntax for assigning functions
In Swift, you assign a function by its name without parentheses to a variable or constant.Step 2: Check each option for correct syntax
let greet = sayHello correctly assigns the function name without calling it. Other options have syntax errors or misuse keywords.Final Answer:
let greet = sayHello -> Option BQuick Check:
Assign function by name without () = let greet = sayHello [OK]
- Adding parentheses when assigning function
- Using 'func' keyword in assignment
- Incorrect variable declaration syntax
func multiplyByTwo(_ number: Int) -> Int {
return number * 2
}
let operation = multiplyByTwo
print(operation(5))Solution
Step 1: Understand function assignment and call
The function multiplyByTwo is assigned to 'operation' without calling it, so 'operation' is a function reference.Step 2: Call the function through the variable
Calling operation(5) runs multiplyByTwo(5), which returns 5 * 2 = 10.Final Answer:
10 -> Option CQuick Check:
Function call via variable returns 10 [OK]
- Expecting variable to hold result, not function
- Confusing function name with string output
- Thinking assignment causes error
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
let sum = add(3, 4)
let operation = add(3, 4)
print(operation(5, 6))Solution
Step 1: Analyze variable assignments
sum is assigned the result of add(3, 4), which is an Int (7). operation is also assigned add(3, 4), so operation is an Int, not a function.Step 2: Check the call to operation(5, 6)
Since operation is an Int, calling operation(5, 6) causes an error because Int is not callable.Final Answer:
Cannot call operation as a function because it holds an Int, not a function -> Option DQuick Check:
Calling Int as function causes error = Cannot call operation as a function because it holds an Int, not a function [OK]
- Assigning function call instead of function reference
- Expecting function call to be callable again
- Ignoring type mismatch errors
makeAdder(3)(5) should return 8.Solution
Step 1: Understand the requirement for returning a function
The function makeAdder must return another function that takes an Int and adds it to x.Step 2: Check which option returns a function type
func makeAdder(_ x: Int) -> (Int) -> Int { return { y in x + y } } returns a closure (function) of type (Int) -> Int that adds x and y, matching the requirement.Final Answer:
func makeAdder(_ x: Int) -> (Int) -> Int { return { y in x + y } } -> Option AQuick Check:
Return function adding x to input = func makeAdder(_ x: Int) -> (Int) -> Int { return { y in x + y } } [OK]
- Returning Int instead of function
- Not using closure syntax for returned function
- Incorrect function signature
Ready to prove it?
Pass the test and this pattern moves unknown
