Functions in Lua

Functions are reusable blocks of code that perform specific tasks. In Lua, functions are first-class values, meaning they can be stored in variables, passed as arguments, and returned from other functions.

Basic Function Definition

Define and call a function:

-- Function definition
function greet()
    print("Hello, World!")
end

-- Function call
greet()  -- Output: Hello, World!

-- Another example
function say_goodbye()
    print("Goodbye!")
    print("See you next time.")
end

say_goodbye()

Functions with Parameters

Functions can accept input values (parameters):

function greet_user(name)
    print("Hello, " .. name .. "!")
end

greet_user("Alice")   -- Hello, Alice!
greet_user("Bob")     -- Hello, Bob!

-- Multiple parameters
function calculate_sum(a, b, c)
    local result = a + b + c
    print("Sum:", result)
end

calculate_sum(5, 10, 15)  -- Sum: 30

Functions with Return Values

Functions can return values to the caller:

function add(a, b)
    return a + b
end

local result = add(10, 5)
print(result)  -- 15

-- Multiple return values
function get_person_info()
    return "Alice", 30, "Engineer"
end

local name, age, profession = get_person_info()
print(name, age, profession)  -- Alice 30 Engineer

Function Variables

Functions can be assigned to variables:

-- Traditional syntax
function multiply(a, b)
    return a * b
end

-- Variable syntax (equivalent)
local divide = function(a, b)
    return a / b
end

print(multiply(4, 5))  -- 20
print(divide(10, 2))    -- 5

Local vs Global Functions

Local Functions (Recommended)

Local functions are only accessible within their scope:

local function secret_operation(x)
    return x * 2 + 10
end

local result = secret_operation(5)  -- Works: 20
-- secret_operation(result)  -- Error if called from outside scope

Global Functions

Global functions are accessible everywhere:

function global_greet(name)
    return "Hello, " .. name
end

-- Can be called from anywhere in the program
print(global_greet("World"))  -- Hello, World

Advanced Function Concepts

Functions as Parameters

Pass functions as arguments to other functions:

function apply_operation(x, y, operation)
    return operation(x, y)
end

function add(a, b) return a + b end
function multiply(a, b) return a * b end

local sum = apply_operation(5, 3, add)        -- 8
local product = apply_operation(5, 3, multiply)  -- 15

print("Sum:", sum)
print("Product:", product)

Anonymous Functions

Create functions without names:

-- Using an anonymous function directly
local numbers = {1, 2, 3, 4, 5}

local doubled = {}
for i, num in ipairs(numbers) do
    doubled[i] = (function(x) return x * 2 end)(num)
end

print(table.concat(doubled, ", "))  -- 2, 4, 6, 8, 10

Closures

Functions that remember their environment:

function create_counter()
    local count = 0
    return function()
        count = count + 1
        return count
    end
end

local counter1 = create_counter()
local counter2 = create_counter()

print(counter1())  -- 1
print(counter1())  -- 2
print(counter2())  -- 1 (independent counter)

Practical Examples

Calculator Functions

-- Math operations
local calculator = {
    add = function(a, b) return a + b end,
    subtract = function(a, b) return a - b end,
    multiply = function(a, b) return a * b end,
    divide = function(a, b) 
        if b ~= 0 then
            return a / b
        else
            error("Division by zero!")
        end
    end
}

-- Using calculator
print(calculator.add(10, 5))      -- 15
print(calculator.multiply(3, 7))  -- 21

String Processing

function format_name(first, last, title)
    local full_name = first .. " " .. last
    if title then
        return title .. " " .. full_name
    end
    return full_name
end

print(format_name("John", "Doe", "Dr."))  -- Dr. John Doe
print(format_name("Jane", "Smith"))        -- Jane Smith

Validation Functions

local function is_positive_number(x)
    return type(x) == "number" and x > 0
end

local function validate_age(age)
    if not is_positive_number(age) then
        return false, "Age must be a positive number"
    end
    if age > 120 then
        return false, "Age seems unrealistic"
    end
    return true, "Valid age"
end

local is_valid, message = validate_age(25)
print(is_valid, message)  -- true Valid age

local is_valid2, message2 = validate_age(-5)
print(is_valid2, message2)  -- false Age must be a positive number

Data Processing Pipeline

function process_data(data, processors)
    local result = data
    for i, processor in ipairs(processors) do
        result = processor(result)
    end
    return result
end

local function normalize(text)
    return string.lower(string.gsub(text, "%s+", " "))
end

local function capitalize(text)
    return string.upper(string.sub(text, 1, 1)) .. string.sub(text, 2)
end

local text = "  HELLO   WORLD  "
local processors = {
    function(t) return string.gsub(t, "^%s+", "") end,  -- trim start
    function(t) return string.gsub(t, "%s+$", "") end,  -- trim end
    normalize,
    capitalize
}

local result = process_data(text, processors)
print(result)  -- Hello world

Function Best Practices

  1. Use local functions when possible for better performance
  2. Give functions descriptive names that explain their purpose
  3. Keep functions small and focused on one task
  4. Add comments for complex logic
  5. Validate inputs and handle edge cases
  6. Return meaningful error messages when operations fail

Next Steps

Now that you understand functions, learn about tables, Lua’s most powerful data structure.

For more function details, see the Lua manual.

Last updated on