Lesson 39Functions
Nested Functions
Functions Inside Functions
Nested functions are defined inside other functions. They're hidden from outside code and can access variables from their parent function!
Key Features
Encapsulation
Hidden from outside code
Closure Over Variables
Access outer scope
Can Be Returned
Create function factories
Organization
Group related helpers
Capturing Values
Nested functions can "capture" variables from their enclosing function. They remember these values even after the outer function returns!
When to Use
- Helper functions only used in one place
- Breaking up complex logic
- Creating function factories
- When you need to capture state
main.swift
// NESTED FUNCTIONS
// Functions defined inside other functions
func outerFunction() {
print("Outer function called")
func innerFunction() {
print("Inner function called")
}
innerFunction() // Call inner from outer
}
outerFunction()
// innerFunction() // ERROR! Not accessible outside
// WHY USE NESTED FUNCTIONS?
// 1. Encapsulation - hide helper functions
// 2. Access to outer function's variables
// 3. Organize complex logic
// ACCESS TO OUTER VARIABLES
func countdown(from start: Int) {
var current = start
func step() {
current -= 1
print(current)
}
while current > 0 {
step() // Uses and modifies 'current'
}
}
countdown(from: 5)
// 4, 3, 2, 1, 0
// RETURNING NESTED FUNCTIONS
func makeCounter() -> () -> Int {
var count = 0
func increment() -> Int {
count += 1
return count
}
return increment
}
let counter1 = makeCounter()
print(counter1()) // 1
print(counter1()) // 2
print(counter1()) // 3
let counter2 = makeCounter() // New counter!
print(counter2()) // 1
// PRACTICAL EXAMPLE: Step-by-step calculation
func calculateTax(on amount: Double, rate: Double) -> Double {
func applyRate() -> Double {
return amount * rate
}
func roundToTwoDecimals(_ value: Double) -> Double {
return (value * 100).rounded() / 100
}
let tax = applyRate()
return roundToTwoDecimals(tax)
}
print(calculateTax(on: 99.99, rate: 0.07)) // 7.0
// MULTIPLE LEVELS OF NESTING
func level1() {
func level2() {
func level3() {
print("Deeply nested!")
}
level3()
}
level2()
}
// CHOOSER PATTERN
func makeOperator(add: Bool) -> (Int, Int) -> Int {
func addNumbers(_ a: Int, _ b: Int) -> Int {
return a + b
}
func subtractNumbers(_ a: Int, _ b: Int) -> Int {
return a - b
}
return add ? addNumbers : subtractNumbers
}
let operation = makeOperator(add: true)
print(operation(10, 5)) // 15Try It Yourself!
Create a `makeMultiplier(by: Int)` function that returns a function to multiply numbers by that value!