Closures, Upvalues and Higher-Order Functions

-- Closures capture local variables from enclosing scopes ("upvalues")
local function make_counter()
    local count = 0
    return function()
        count = count + 1
        return count
    end
end
local c1, c2 = make_counter(), make_counter()
print(c1(), c1(), c2())       --> 1  2  1 (independent state)

-- Shared upvalues
local function make_account(balance)
    return {
        deposit  = function(v) balance = balance + v end,
        withdraw = function(v) balance = balance - v end,
        balance  = function() return balance end,
    }
end
local acc = make_account(100)
acc.deposit(50); acc.withdraw(30)
print(acc.balance())          --> 120

-- Each loop iteration creates a fresh local
local fns = {}
for i = 1, 3 do fns[i] = function() return i end end
print(fns[1](), fns[2](), fns[3]())   --> 1  2  3

-- Higher-order functions
local function map(t, f)
    local out = {}
    for i, v in ipairs(t) do out[i] = f(v) end
    return out
end
local function filter(t, pred)
    local out = {}
    for _, v in ipairs(t) do if pred(v) then out[#out + 1] = v end end
    return out
end
local function reduce(t, f, init)
    local acc = init
    for _, v in ipairs(t) do acc = f(acc, v) e
…