0Pricing
Lua Academy · Lesson

Generic for and break

Use generic for with pairs/ipairs and control loop flow with break.

Generic for and break is a free Lua Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Generic for Protocol

Lua's generic for loop works with an iterator function. The syntax is for vars in iter_func, state, init do. On each iteration, Lua calls iter_func(state, lastVar) and assigns return values to vars. The loop stops when the first return value is nil.

-- Manual use of next() iterator
local t = {a=1, b=2, c=3}
local key, val = next(t, nil)   -- first entry
while key ~= nil do
  print(key, val)
  key, val = next(t, key)       -- advance
end

pairs() for All Keys

pairs(t) returns an iterator that traverses all key-value pairs in a table, including string keys, integer keys, and mixed. The iteration order for non-integer keys is unspecified (hash order). Array portion and hash portion are both included.

local config = {
  host = "localhost",
  port = 8080,
  debug = true,
  [1] = "first",
}

for key, value in pairs(config) do
  print(key, value)
end
-- Prints all 4 entries in any order

ipairs() for Array Keys

ipairs(t) iterates over integer keys starting from 1, stopping at the first nil value. It is safe, predictable, and preserves order. Use ipairs for array-like tables when order matters and you want to stop at the first hole.

local fruits = {"apple", "banana", "cherry"}

for i, fruit in ipairs(fruits) do
  print(i, fruit)
end
-- 1  apple
-- 2  banana
-- 3  cherry

-- stops at first nil
local t = {10, 20, nil, 40}
for i, v in ipairs(t) do
  print(i, v)  -- only 1,10 and 2,20
end

pairs vs ipairs

Know when to use each: ipairs is for ordered sequential arrays; pairs is for dictionaries or mixed tables. ipairs stops at the first nil hole; pairs visits every non-nil key. For pure arrays, ipairs is more idiomatic.

local mixed = {10, 20, key="val", 30}

-- ipairs only sees array part in order
print("ipairs:")
for i, v in ipairs(mixed) do
  print(i, v)  -- 1:10, 2:20, 3:30
end

-- pairs sees everything
print("pairs:")
for k, v in pairs(mixed) do
  print(k, v)  -- 1:10, 2:20, 3:30, key:val
end

Custom Iterator with Closure

You can write your own iterator as a closure. The factory function returns a stateful closure that advances position on each call. When there is nothing left to return, it returns nil to stop the generic for.

local function range(from, to, step)
  step = step or 1
  local i = from - step
  return function()
    i = i + step
    if i <= to then return i end
  end
end

for n in range(1, 10, 2) do
  io.write(n .. " ")
end
print()  -- 1 3 5 7 9

string.gmatch as Iterator

string.gmatch(s, pattern) returns an iterator over all matches of the pattern in string s. It is commonly used to split strings, extract tokens, or find all occurrences of a pattern.

local sentence = "the quick brown fox"

for word in string.gmatch(sentence, "%a+") do
  print(word)
end
-- the
-- quick
-- brown
-- fox

break in Generic for

You can exit a generic for loop early using break. This is useful for searching: iterate until a match is found, then break. After breaking, execution continues at the statement after end.

local inventory = {
  {name="sword", damage=50},
  {name="shield", armor=30},
  {name="bow", damage=35},
}

local target = "shield"
for i, item in ipairs(inventory) do
  if item.name == target then
    print("Found at index", i)
    break
  end
end

Modifying Tables During Iteration

Never insert or remove keys from a table while iterating with pairs() — the behavior is undefined (some changes may be seen, others skipped). If you need to modify a table, collect changes in a temporary list and apply them after the loop.

local t = {a=1, b=2, c=3, d=4}
local toDelete = {}

-- Collect keys to delete
for k, v in pairs(t) do
  if v % 2 == 0 then
    toDelete[#toDelete+1] = k
  end
end

-- Delete after iteration
for _, k in ipairs(toDelete) do
  t[k] = nil
end
-- t = {a=1, c=3}

Enumerate Pattern

When you need both the index and the value, use ipairs which provides both. When you only need values and don't care about the index, you can use _ as a conventional "don't-care" variable name for the index.

local colors = {"red", "green", "blue"}

-- With index
for i, color in ipairs(colors) do
  print(i .. ": " .. color)
end

-- Ignore index with _
for _, color in ipairs(colors) do
  print(color)  -- just the values
end

next() Directly

next(t, key) is the underlying traversal function. It returns the next key-value pair after key, or nil if there are no more. next(t, nil) gives the first entry. You can use next(t) ~= nil to check if a table is non-empty — faster than counting.

local function isEmpty(t)
  return next(t) == nil
end

print(isEmpty({}))       -- true
print(isEmpty({1,2,3}))  -- false
print(isEmpty({a=1}))    -- false

Quick Check

Which iterator stops at the first nil hole in a table?

Recap: Generic for and break

Summary:

  • pairs(t) — all keys, any order
  • ipairs(t) — integer keys 1..n, ordered, stops at nil
  • Custom iterators: return a closure that returns nil to stop
  • break exits the loop early
  • Never modify a table mid-pairs; collect changes and apply after
  • next(t) == nil — fast empty check

Frequently asked questions

Is the “Generic for and break” lesson free?

Yes — the full text of “Generic for and break” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.

What will I learn in “Generic for and break”?

Use generic for with pairs/ipairs and control loop flow with break. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Lua Academy?

No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Generic for and break” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Lua Academy lesson?

Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. if, elseif and else Statements
  2. while and repeat-until Loops
  3. Numeric for Loop
  4. Generic for and break
← Back to Lua Academy