Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't modify loop-variable in lua [duplicate]

Tags:

lua

im trying this in lua:

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

I would expect the following output:

1,4,7,10

However, it seems like i is getting not affected, so it gives me:

1,2,3,4,5,6,7,8,9,10

Can someone tell my a bit about the background concept and what is the right way to modify the counter variable?

like image 837
Daveman Avatar asked Dec 16 '15 16:12

Daveman


3 Answers

As Colonel Thirty Two said, there is no way to modify a loop variable in Lua. Or rather more to the point, the loop counter in Lua is hidden from you. The variable i in your case is merely a copy of the counter's current value. So changing it does nothing; it will be overwritten by the actual hidden counter every time the loop cycles.

When you write a for loop in Lua, it always means exactly what it says. This is good, since it makes it abundantly clear when you're doing looping over a fixed sequence (whether a count or a set of data) and when you're doing something more complicated.

for is for fixed loops; if you want dynamic looping, you must use a while loop. That way, the reader of the code is aware that looping is not fixed; that it's under your control.

like image 168
Nicol Bolas Avatar answered Oct 19 '22 08:10

Nicol Bolas


When using a Numeric for loop, you can change the increment by the third value, in your example you set it to 1.

To see what I mean:

for i = 1,10,3 do
    print(i)
end

However this isn't always a practical solution, because often times you'll only want to modify the loop variable under specific conditions. When you wish to do this, you can use a while loop (or if you want your code to run at least once, a repeat loop):

local i = 1
while i < 10 do
    print(i)
    i = i + 1
end

Using a while loop you have full control over the condition, and any variables (be they global or upvalues).

like image 39
warspyking Avatar answered Oct 19 '22 09:10

warspyking


All answers / comments so far only suggested while loops; here's two more ways of working around this problem:


If you always have the same step size, which just isn't 1, you can explicitly give the step size as in for i =start,end,stepdo … end, e.g. for i = 1, 10, 3 do … or for i = 10, 1, -1 do …. If you need varying step sizes, that won't work.


A "problem" with while-loops is that you always have to manually increment your counter and forgetting this in a sub-branch easily leads to infinite loops. I've seen the following pattern a few times:

local diff = 0
for i = 1, n do
   i = i+diff
   if i > n then  break  end
   -- code here
   -- and to change i for the next round, do something like
   if some_condition then
       diff = diff + 1  -- skip 1 forward
   end
end

This way, you cannot forget incrementing i, and you still have the adjusted i available in your code. The deltas are also kept in a separate variable, so scanning this for bugs is relatively easy. (i autoincrements so must work, any assignment to i below the loop body's first line is an error, check whether you are/n't assigning diff, check branches, …)

like image 1
nobody Avatar answered Oct 19 '22 08:10

nobody