Reading — step 1 of 5
Learn
for k, v in expr do ... end is Lua's generic for. The right side must produce three values: an iterator function, a state, and a control variable.
Stateless iterator — like ipairs:
local function range(n)
return function(_, i)
i = i + 1
if i <= n then return i, i end
end, nil, 0
end
for _, v in range(5) do print(v) end -- 1 2 3 4 5
The iterator function receives (state, control) and returns the next pair (or nil to stop). State and control are seeded by the second and third return.
Stateful iterator (with closure):
local function range(start, stop)
local i = start - 1
return function()
i = i + 1
if i <= stop then return i end
end
end
for v in range(10, 15) do print(v) end -- 10..15
Closure captures i. Each call returns next value or nil. Simpler — and sufficient most of the time.
Pairs/ipairs comparison:
for k, v in pairs(t) do ... end -- ALL keys, arbitrary order
for i, v in ipairs(t) do ... end -- integer keys 1..n only
Custom iterator with closure — file lines:
local function lines(filename)
local f = io.open(filename, "r")
return function()
local line = f:read("*l")
if line then return line
else f:close() end
end
end
for line in lines("input.txt") do
print(line)
end
Coroutine-based iterator (very flexible, slight perf overhead):
local function fibs()
return coroutine.wrap(function()
local a, b = 0, 1
while true do
coroutine.yield(b)
a, b = b, a + b
end
end)
end
local it = fibs()
for _ = 1, 10 do print(it()) end
Coroutine generators feel like Python generators — write the producer naturally, consumer iterates.
Built-in iterators worth knowing:
pairs(t)— all key/valueipairs(t)— integer-indexedstring.gmatch(s, pat)— pattern matchesio.lines(f)— file linescoroutine.wrap(...)— coroutine to iterator
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…