Part of Learn Lua with NeoVim

Learn Lua in Neovim: Functions — Basics, Parameters vs Arguments & return | Episode 12

Sandy LaneSandy Lane

Video: Learn Lua in Neovim: Functions — Basics, Parameters vs Arguments & return | Episode 12 by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

Lua Functions: Basics, Parameters vs Arguments, and return

function name(params) ... end to define. name(args) to call. return value to send a result back. Parameters are placeholders; arguments are the actual values you pass in.

Functions package up code so you can call it many times with different inputs. They're the second pillar of Lua programs (after tables, which we'll meet in episode 17).

Defining a function

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

greet("Alice")
greet("Bob")
greet("Lua")

Output:

Hello, Alice!
Hello, Bob!
Hello, Lua!

Three keywords:

  • function — start a function definition.
  • function name(params) — give it a name and a parameter list.
  • end — close the body.

name is the function. params is the parameter list. The body runs each time the function is called.

Parameters vs arguments

The terms get confused, but they're different:

  • Parameters are the names in the function definition. name in function greet(name).
  • Arguments are the values you pass when calling. "Alice" in greet("Alice").

Inside the function, the parameter holds the argument's value:

function greet(name)
  -- here, `name` is "Alice" if called with greet("Alice")
end

The names parameter and argument carry meaning when reading docs. "Function takes two parameters" describes the signature; "we passed three arguments" describes a call.

Return values

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

local result = add(10, 20)
print("10 + 20 = " .. result)
print("3 + 7 = " .. add(3, 7))

return value sends a value back. The caller receives it as the function call's value.

add(3, 7) evaluates to 10. You can use it in expressions like any other value.

Functions without return

function greet(name)
  print("Hello, " .. name)
end

local x = greet("Alice")
print(x)  -- nil

A function that doesn't return anything implicitly returns nil. This is fine for "do something" functions like greet.

return exits the function

function describe(n)
  if n == 0 then
    return "zero"
  end
  if n > 0 then
    return "positive"
  end
  return "negative"
end

return immediately exits — once you've returned, the rest of the body is skipped. Useful for early exits and guard clauses:

function safe_divide(a, b)
  if b == 0 then return nil end
  return a / b
end

A boolean function

function is_even(n)
  return n % 2 == 0
end

print("4 is even: " .. tostring(is_even(4)))
print("7 is even: " .. tostring(is_even(7)))

The body is one expression: n % 2 == 0. Lua evaluates it (true or false) and return sends the boolean back.

tostring(...) is needed because .. only auto-converts numbers, not booleans.

Local functions

local function square(x)
  return x * x
end

Just like variables, prefer local function to plain function (which creates a global). The forward-decl idiom for recursive locals:

local fact
fact = function(n)
  if n <= 1 then return 1 end
  return n * fact(n - 1)
end

The two-step is needed because at the moment local fact = function(n) ... fact(n-1) ... end is parsed, fact doesn't exist yet on the right side. Splitting it lets the body see the local.

Or use the cleaner:

local function fact(n)
  if n <= 1 then return 1 end
  return n * fact(n - 1)
end

local function desugars to "declare local first, assign function second" — handles the recursion automatically.

Functions as values

In Lua, functions are first-class: you can store them in variables, pass them as arguments, return them from other functions. Episode 15 dives into this; for now, just know:

local op = add        -- store a reference
print(op(2, 3))       -- 5

local fn = function(x) return x * 2 end   -- anonymous function
print(fn(10))         -- 20

Default parameter values

Lua doesn't have built-in default values, but the or idiom from episode 8 covers the common case:

function greet(name)
  name = name or "stranger"
  print("Hello, " .. name)
end

greet()         -- Hello, stranger
greet("Alice")  -- Hello, Alice

For multiple defaults:

function rect(width, height, color)
  width = width or 10
  height = height or 5
  color = color or "blue"
  -- ...
end

Verbose but clear.

Missing arguments are nil

function describe(name, age)
  print(name)  -- "Alice"
  print(age)   -- nil
end

describe("Alice")

Lua doesn't error on missing arguments — they're just nil. That's why the or default trick works.

Conversely, extra arguments are silently dropped:

function add(a, b)
  return a + b
end
add(1, 2, 3)  -- returns 3; the third arg is ignored

Common stumbles

Forgetting return. A function that should produce a value but only prints it returns nil. Make sure to return if the caller needs the result.

Using the function before defining it. Lua reads top-to-bottom; calling greet("Alice") before function greet is defined returns nil (and crashes when you try to call it).

Confusing parameters and arguments. Parameters are named in the definition; arguments are values at the call site. A function "takes parameters" but "is called with arguments."

Forgetting local function. Plain function name(...) creates a global. Subtle bug source. Always local function.

Recursion without forward declaration. local fact = function(n) ... fact(...) ... end has fact undefined inside the body. Use local function fact(n) ... end or the two-step idiom.

What's next

Episode 13: multiple returns and variadics. Lua functions can return more than one value (return a, b), and accept variable numbers of arguments (function f(...)).

Recap

function name(params) body end to define; local function for non-globals. Parameters are placeholders, arguments are values. return value sends a result back; missing return = nil. Missing arguments are nil; extra arguments are ignored. Functions are first-class values — store them, pass them, return them. Default parameters via param = param or default.

Next episode: multiple returns and variadics.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.