Справочное руководство по языку Lua 5.1 :: 2.4.5 - Управляющие конструкции



2.4.5 – Оператор For

Оператор for допускает простую и расширенную формы записи.

В простой форме for выполняет блок кода до тех пор, пока переменная цикла, изменяеющаяся в арифметической прогрессии, не достигнет установленного порога.


    stat ::= for Name ' = ' exp ',' exp [', ' exp] do block end

block повторяется для переменной цикла name начиная со значения первого выражения exp, до тех пор пока выполняется второе выражение exp с шагом третьeго выражения exp.

Таким образом, запись


    for v = e1, e2, e3 do block end

эквивалентна коду


    do
   
       local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
      
       if not (var and limit and step) then error() end
      
       while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
      
         local v = var
       
         block
       
         var = var + step
       
       end
      
     end
   

Обратите внимание, что:

  • Все три логических выражения вычисляются только один раз перед началом цикла, причем полученные значения должны быть числами.
  • var, limit, и step - неявные переменные, мы условно именовали их здесь для объяснения логики работы
  • Если выражение step (шаг) отсутствует, то по умолчанию используется 1
  • Для выхода из цикла for используйте break.
  • Переменная v является локальной для цикла; вы не сможете использовать ее значение после выхода из цикла for. Если вам необходимо значение этой переменной, присвойте его другой переменной перед выходом из цикла.

Расширенная форма оператора for реализована с использованием функций итераторов. На каждом обороте для получения нового значения переменной цикла вызывается итератор. Цикл заканчивается, когда итератор вернет nil. Синтаксис расшеренного оператора for:


    stat ::= for namelist in explist1 do block end

    namelist ::= Name {', '~ Name}
   

Запись


    for var_1, ···, var_n in explist do block end
   

можно представить как


    do
   
       local f, s, var = explist
      
       while true do
      
         local var_1, ···, var_n = f(s, var)
       
         var = var_1
       
         if var == nil then break end
       
         block
       
       end
      
     end
   

Заметим, что

  • explist вычисляется только однажды. Его результатом является функция-итератор, таблица состояний и начальное значение индекса
  • f, s, и var неявные переменные, именованные здесь для примера
  • Выйти из цикла можно с помощью оператора break.
  • Переменная var_i является локальной; вы не сможете использовать ее значение после выхода из for. Если вам необходимо ее значение, заранее сохраните его в другой переменной.