Advanced Functions: Closures, Higher-Order Functions, and More
Lesson Overview
Now that you understand basic functions, it's time to explore advanced conceptsthat make Lua powerful and flexible. This lesson covers closures, higher-order functions, and functional programming patterns.
These concepts are essential for building modular, reusable, and elegant code.
Lesson Objectives
By the end of this lesson, you will be able to:
- Understand and create closures
- Use higher-order functions
- Pass functions as arguments
- Return functions from functions
- Apply functional programming patterns
What Are Closures?
A closure is a function that remembers the variables from its outer scope, even after that scope has finished executing.
Think of it as a function that "captures" its environment.
function createCounter()
local count = 0 -- captured variable
return function()
count = count + 1
return count
end
end
local counter = createCounter()
print(counter()) -- 1
print(counter()) -- 2
print(counter()) -- 3The inner function remembers count even after createCounter has finished!
Why Closures Matter
Closures are used for:
- • Data Privacy - Hide internal state
- • State Management - Maintain state across calls
- • Factory Functions - Create customized functions
- • Callbacks - Pass context to event handlers
Higher-Order Functions
A higher-order function is a function that:
- • Takes one or more functions as arguments, OR
- • Returns a function as its result
Example: Function as Argument
function applyTwice(func, value)
return func(func(value))
end
function double(x)
return x * 2
end
print(applyTwice(double, 5)) -- Outputs: 20Returning Functions
Functions can return other functions, creating powerful patterns.
function createMultiplier(factor)
return function(x)
return x * factor
end
end
local triple = createMultiplier(3)
local quadruple = createMultiplier(4)
print(triple(10)) -- Outputs: 30
print(quadruple(10)) -- Outputs: 40Practical Example: Map Function
Apply a function to every element in a table.
function map(tbl, func)
local result = {}
for i, v in ipairs(tbl) do
result[i] = func(v)
end
return result
end
local numbers = {1, 2, 3, 4, 5}
local squared = map(numbers, function(x) return x * x end)
-- squared = {1, 4, 9, 16, 25}Practical Example: Filter Function
Select elements that match a condition.
function filter(tbl, predicate)
local result = {}
for _, v in ipairs(tbl) do
if predicate(v) then
table.insert(result, v)
end
end
return result
end
local numbers = {1, 2, 3, 4, 5, 6}
local evens = filter(numbers, function(x) return x % 2 == 0 end)
-- evens = {2, 4, 6}Advanced Pattern: Memoization
Cache function results to avoid redundant calculations.
function memoize(func)
local cache = {}
return function(x)
if cache[x] == nil then
cache[x] = func(x)
end
return cache[x]
end
end
local slowFibonacci = function(n)
if n <= 1 then return n end
return slowFibonacci(n-1) + slowFibonacci(n-2)
end
slowFibonacci = memoize(slowFibonacci)Best Practices
- Keep closures simple and focused
- Document captured variables
- Avoid creating closures in tight loops
- Use closures for data privacy
- Test closure behavior carefully
Summary
In this lesson, you learned:
- Closures capture and remember their environment
- Higher-order functions work with other functions
- Functions can be passed as arguments and returned
- Functional patterns like map, filter, and memoization
- These concepts enable powerful, elegant code
Ready to test your knowledge?
Take the quiz to verify your understanding of advanced functions.