Part of Learn Lua with NeoVim

Learn Lua in Neovim: Numeric For Loops — Count, Step & Countdown | Episode 9

Sandy LaneSandy Lane

Video: Learn Lua in Neovim: Numeric For Loops — Count, Step & Countdown | Episode 9 by Taught by Celeste AI - AI Coding Coach

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

Lua Numeric For Loops: count, step, and a Multiplication Table

for i = 1, 5 do ... end for the basics. Add a step value for 2, 4, 6 ... or 5, 4, 3 ... countdowns. Multiplication tables and summations in three lines.

Lua has two kinds of for loop: the numeric for (today) and the generic for (covered when we hit tables). Numeric for is for "count from N to M" — the most common case.

The basics

for i = 1, 5 do
  print(i)
end

Output:

1
2
3
4
5

Three keywords frame the loop:

  • for — start the loop.
  • do — required after the range; ends the loop's header.
  • end — closes the body.

i = 1, 5 means "start at 1, go up to 5 (inclusive)." i is created fresh each iteration; it's local to the loop.

With a step

for i = 2, 10, 2 do
  print(i)
end

Output:

2
4
6
8
10

A third number after the range is the step — how much to add each iteration. Default step is 1.

Counting down

for i = 5, 1, -1 do
  print(i)
end
print("Go!")

Output:

5
4
3
2
1
Go!

Negative step counts down. Without -1, the loop wouldn't run at all — the default step of +1 from 5 would never reach 1.

Multiplication table

local num = 7
for i = 1, 10 do
  print(num .. " x " .. i .. " = " .. num * i)
end

Output:

7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
... up to ...
7 x 10 = 70

i takes values 1 through 10. Each iteration computes num * i and prints a row.

Summing 1 to 100

local sum = 0
for i = 1, 100 do
  sum = sum + i
end
print("Sum: " .. sum)

Output:

Sum: 5050

Initialise an accumulator outside the loop, add to it each iteration. Standard pattern for any reduction (sum, product, max, count).

The closed-form (n * (n + 1) / 2) is faster — but the loop teaches the pattern, and you'll need it when there's no closed form.

What about non-integer steps?

for x = 0.0, 1.0, 0.1 do
  print(x)
end

Works, but watch out for floating-point quirks — the loop might stop at 0.9 instead of 1.0 due to accumulated rounding error. For predictable iteration over decimals, use integer counts and divide:

for i = 0, 10 do
  local x = i / 10
  print(x)
end

Loop variable is local

for i = 1, 3 do
  print(i)
end
print(i)   -- nil! i doesn't exist out here.

The loop variable is created fresh each iteration and disappears when the loop ends. You can't reach into it from outside. To remember the final value, copy it:

local last
for i = 1, 5 do
  last = i
end
print(last)  -- 5

Modifying the counter doesn't help

for i = 1, 5 do
  print(i)
  i = i + 100  -- ignored! Lua re-binds i each iteration.
end

Each iteration starts with i set from the loop's internal counter, not from the previous iteration's value. Modifying i inside the body is harmless and pointless.

To skip iterations, use if:

for i = 1, 10 do
  if i % 2 == 0 then
    print(i)  -- only evens
  end
end

Or use goto continue (Lua 5.2+):

for i = 1, 10 do
  if i % 2 ~= 0 then goto continue end
  print(i)
  ::continue::
end

goto and labels are rare in Lua but goto continue is the canonical "skip iteration" pattern.

Range gotchas

for i = 5, 1 do
  print(i)
end

This prints nothing. The default step is +1; from 5 it can't reach 1. Use for i = 5, 1, -1 do for descending.

for i = 1, 10, 0 do
  -- infinite loop
end

Step of zero never advances. Avoid.

Common stumbles

Forgetting the loop variable is local. Trying to read i after the loop returns nil.

Wrong step direction. for i = 10, 1 loops zero times because step defaults to +1. Add -1 for descending.

Floating-point step. for x = 0.0, 1.0, 0.1 may behave unexpectedly at the boundary. Use integers and divide.

Mutating the counter inside. Doesn't change iteration. Each step rebinds i from the internal counter.

Off-by-one in the upper bound. Lua's for i = 1, n is inclusive — both 1 and n run. Different from range(1, n) in Python (which excludes n).

What's next

Episode 10: while and repeat loops. When you don't know the count up front — looping until a condition is met. Plus the difference between top-tested and bottom-tested loops.

Recap

for i = start, stop do ... end for numeric loops; both ends are inclusive. Add a step: for i = 1, 10, 2 do. Negative step for countdowns. Loop variable is local; don't expect it to outlive the loop. Mutating the counter inside the body is a no-op. Use the loop for any "count and act" operation; for early exit use break (next episode).

Next episode: while and repeat loops.

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.