3.3 – Операторы
3.3.1 – Блоки
block ::= {stat}
пустые операторы
stat ::= ‘;’
a = b + c (print or io.write)('done')
a = b + c(print or io.write)('done') a = b + c; (print or io.write)('done')
парсер
;(print or io.write)('done')
stat ::= do block end
return
3.3.2 – Порции
порция
chunk ::= block
_ENV_ENVзагружаетпрограмму luac
Примечание: Интерпретатор — программа (разновидность транслятора), выполняющая интерпретацию, … читать далее
3.3.3 – Присваивание
stat ::= varlist ‘=’ explist varlist ::= var {‘,’ var} explist ::= exp {‘,’ exp}
согласовываетсяnil
i = 3 i, a = i+1, 20
aaia
x, y = y, x
xy
x, y, z = y, z, x
xyzt = valsettable_event(t,i,val)settable_eventx = val_ENV.x = val
3.3.4 – Управляющие структуры
ifwhilerepeat
stat ::= while exp do block end stat ::= repeat block until exp stat ::= if exp then block {elseif exp then block} [else block] end
forfalsenilnilfalserepeatuntiluntilgoto
stat ::= goto Name stat ::= label label ::= ‘::’ Name ‘::’
gotoнедействующими операторамиbreakwhilerepeatfor
stat ::= break
breakreturnreturn
stat ::= return [‘;’]
returnreturndo return endreturn
3.3.5 – Оператор for
forforарифметическую прогрессию
stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end
blocknameexpexpexpfor
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 var = var - step while true do var = var + step if (step >= 0 and var > limit) or (step < 0 and var < limit) then break end local v = var block end end
- Все три управляющих выражения вычисляются только один раз, перед началом цикла. Все они должны быть приведены в числах.
- var (переменная), limit (предел), и step (шаг) — невидимые (неявные) переменные. Имена, показанные здесь, приведены только для пояснения.
- Если третье выражение (step) отсутствует, то используется шаг равный 1.
- Для выхода из цикла for можно использовать break и goto.
- Переменная цикла v является локальной для тела цикла. Если потребуется её значение после цикла, назначьте его в другую переменную перед выходом из цикла.
forитераторамиnilfor
stat ::= for namelist in explist do block end namelist ::= Name {‘,’ Name}
for
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) if var_1 == nil then break end var = var_1 block end end
- explist вычисляется только один раз. Его результатами являются функция iterator, state и начальное значение для первой переменной итератора.
- f, s, и var являются неявными переменными. Имена, используемые здесь, только для пояснения.
- Для выхода из цикла for можно использовать break.
- Переменные цикла var_i являются локальными для цикла, их значения нельзя использовать после завершения цикла for.
Если все же эти значения потребовались, то присвойте их другим переменным перед тем как прервать цикл или выйти из него.
6.3 – Модули
package
require (modname)
modnamerequirepackage.loadedloaderrequirerequirerequirepackage.preloadrequireвсе-в-одномrequiremodnamenilrequirepackage.loadednilpackage.loadedrequiretruerequirepackage.loadedrequire
package.config
- Первая строка — значение разделителя каталогов. По умолчанию им является ‘\‘ для Windows и » для всех остальных систем.
- Вторая строка — символ, разделяющий шаблоны в пути. По умолчанию это ‘;‘.
- Третья строка — значение, которое маркирует точки замен в шаблоне. По умолчанию это ‘?‘.
- Четвертой строкой является строковое значение, которое в пути Windows заменяется каталогом выполнения. По умолчанию это ‘!‘.
- Пятой строкой является знак игнорирования всего текста после него, при построении имени функции luaopen_. По умолчанию это ‘-‘.
package.searchers
функцией поисковикомзагрузчикnil
"./?.so;./?.dll;/usr/local/?/init.so"
foo./foo.so./foo.dll/usr/local/foo/init.soluaopen_a.b.c-v2.1luaopen_a_b_cвсе-в-одномa.b.caluaopen_a_b_c
package.searchpath (name, path ])
namepathшаблоновnameseprep
"./?.lua;./?.lc;/usr/local/?/init.lua"
foo.a./foo/a.lua./foo/a.lc/usr/local/foo/a/init.luanil
2.5 – Tables
The table type implements associative arrays.
An associative array is an array
that can be indexed not only with numbers,
but also with strings or any other value of the language,
except nil.
Moreover, tables have no fixed size;
you can add as many elements as you want to a table dynamically.
Tables are the main (in fact, the only) data structuring mechanism in Lua,
and a powerful one.
We use tables to represent ordinary arrays,
symbol tables, sets, records, queues, and other data structures,
in a simple, uniform, and efficient way.
Lua uses tables to represent packages as well.
When we write ,
we mean «the entry from the package».
For Lua, that means
«index the table using the string as the key».
Tables in Lua are neither values nor variables;
they are objects.
If you are familiar with arrays in Java or Scheme,
then you have a fair idea of what we mean.
However, if your idea of an array comes from C or Pascal,
you have to open your mind a bit.
You may think of a table as a dynamically allocated object;
your program only manipulates references (or pointers) to them.
There are no hidden copies or creation of new tables
behind the scenes.
Moreover, you do not have to declare a table in Lua;
in fact, there is no way to declare one.
You create tables by means of a constructor expression,
which in its simplest form is written as :
a = {} -- create a table and store its reference in `a' k = "x" a = 10 -- new entry, with key="x" and value=10 a = "great" -- new entry, with key=20 and value="great" print(a) --> 10 k = 20 print(a) --> "great" a = a + 1 -- increments entry "x" print(a) --> 11
a = {} a = 10 b = a -- `b' refers to the same table as `a' print(b) --> 10 b = 20 print(a) --> 20 a = nil -- now only `b' still refers to the table b = nil -- now there are no references left to the table
Each table may store values with different types of indices
and it grows as it needs to accommodate new entries:
a = {} -- empty table -- create 1000 new entries for i=1,1000 do a = i*2 end print(a) --> 18 a = 10 print(a) --> 10 print(a) --> nil
nilnil
To represent records, you use the field name as an index.
Lua supports this representation by
providing as syntactic sugar for .
So, we could write the last lines of the previous example
in a cleanlier manner as
a.x = 10 -- same as a = 10 print(a.x) -- same as print(a) print(a.y) -- same as print(a)
A common mistake for beginners is to confuse with .
The first form represents , that is, a table indexed by
the string .
The second form is a table indexed by the value of the variable .
See the difference:
a = {} x = "y" a = 10 -- put 10 in field "y" print(a) --> 10 -- value of field "y" print(a.x) --> nil -- value of field "x" (undefined) print(a.y) --> 10 -- value of field "y"
To represent a conventional array,
you simply use a table with integer keys.
There is no way to declare its size;
you just initialize the elements you need:
-- read 10 lines storing them in a table a = {} for i=1,10 do a = io.read() end
nil
-- print the lines for i,line in ipairs(a) do print(line) end
Since you can index a table with any value,
you can start the indices of an array with
any number that pleases you.
However, it is customary in Lua to start arrays with one
(and not with zero, as in C)
and the standard libraries stick to this convention.
Because we can index a table with any type,
when indexing a table
we have the same subtleties that arise in equality.
Although we can index a table both with the
number and with the string ,
these two values are different (according to equality)
and therefore denote different positions in a table.
By the same token, the strings , ,
and all denote different positions.
When in doubt about the actual types of your indices,
use an explicit conversion to be sure:
i = 10; j = "10"; k = "+10" a = {} a = "one value" a = "another value" a = "yet another value" print(a) --> another value print(a) --> yet another value print(a) --> one value print(a) --> one value
Copyright 2003–2004 Roberto Ierusalimschy. All rights reserved. |
Специальные функции
Некоторые имена функций таблиц (методов) зарезервированы, и они несут особый смысл:
* __add(a, b), __sub(a, b), __div(a, b), __mul(a, b), __mod(a, b), __pow(a, b) — вызываются, когда выполняются арифметические операции над таблицей
* __unm(a) — унарная операция «минус» (когда пишут что-то типа «x = -x»)
* __lt(a, b), __le(a, b), __eq(a, b) — вычисляют результат сравнения (<, <=, ==)
* __len(a) — вызывается, когда делается «#a»
* __concat(a, b) — вызывается при «a..b»
* __call(a, …) — вызывается при «a()». Переменные аргументы — это аргументы при вызове
* __index(a, i) — обращение к a, при условии, что такого элемента не существует
* __newindex(a, i, v) — создание «a = v»
* __gc(a) — когда объект удаляется при сборке мусора
Подменяя эти методы, можно перегружать операторы и использовать синтаксис языка для своих целей. Главное не переусердствовать.
3 ответа
Лучший ответ
С моей стороны это всего лишь догадки, но:
1. Это сложно реализовать в однопроходном компиляторе.
Компилятор байт-кода Lua реализован как однопроходный рекурсивный анализатор спуска, который немедленно генерирует код. Он не анализирует отдельную структуру AST, а затем во втором проходе преобразует ее в байт-код.
Это накладывает некоторые ограничения на грамматику и семантику. В частности, в этой модели действительно сложно поддерживать все, что требует произвольных ссылок вперед или вперед. Это означает, что присвоения уже трудно анализировать. Учитывая что-то вроде:
Когда вы разбираете , вы не понимаете, что на самом деле анализируете назначение, пока не нажмете после того, как вы уже проанализировали и сгенерировали код для этого. Компилятор Lua из-за этого имеет большую сложность только для обработки присваиваний.
Поддержка самостоятельного назначения сделает это еще труднее. Что-то вроде:
Необходимо перевести на:
Но в тот момент, когда компилятор попадает в , он уже забыл о . Это возможно, но непросто.
2. Это может плохо сказаться на грамматике
Lua фактически не имеет в грамматике каких-либо операторов или разделителей строк. Пробелы игнорируются, и точки с запятой не используются. Ты можешь сделать:
Или же:
И Lua одинаково доволен обоими. Сохранять такую грамматику недвусмысленной непросто. Я не уверен, но операторы самостоятельного присваивания могут усложнить задачу.
3. Это не очень хорошо с несколькими заданиями
Lua поддерживает множественное назначение, например:
Мне даже не ясно, что это значило бы, если бы вы попытались сделать:
Вы можете ограничить операторы самостоятельного присваивания одним назначением, но тогда вы просто добавили странный угловой случай, о котором люди должны знать.
При всем этом не совсем ясно, достаточно ли полезны операторы самоназначения, чтобы иметь дело с указанными выше проблемами.
66
munificent
3 Дек 2013 в 21:47
Другая причина, по которой Lua не имеет операторов самоназначения, заключается в том, что доступ к таблицам может быть перегружен метатаблицами, чтобы иметь произвольные побочные эффекты. Для самостоятельного назначения вам нужно выбрать десахар.
В
Или в
Первая версия запускает метаметод для дважды, а вторая — только один раз. Отсутствие самоопределения в языке и принуждение к откровенности помогает избежать этой двусмысленности.
12
hugomg
3 Янв 2014 в 16:22
Я думаю, вы могли бы просто переписать этот вопрос как
Обычно это компромисс, который разработчики языка делают, исходя из своего видения того, для чего предназначен язык, и своих целей.
В случае Lua язык предназначен для использования в качестве встроенного языка сценариев, поэтому любые изменения, которые делают язык более сложным или потенциально делают компилятор / среду выполнения даже немного больше или медленнее, могут противоречить этой цели.
Если вы реализуете каждую крошечную функцию, вы можете получить язык «кухонной раковины»: ADA , кто-нибудь?
И, как вы говорите, это просто синтаксический сахар.
15
Roddy
20 Ноя 2013 в 09:32
Примеры циклов обхода массивов
--lua local arr = {40, 50, 20, 10} -- массив arr, элементы: = 40, = 50, = 20, = 10 log ("clear") -- очистить лог log ("mode compact") -- компактный режим for i = 1, #arr do -- #arr - размер массива arr log (i, arr) end log() -- или так for i, value in ipairs(arr) do log (i, value) end -- Когда в массиве отсутствуют пустые элементы (nil) между #arr и ipairs разницы нет.
--lua local arr = { = 40, = 50, = 10} -- массив arr, элементы: = 40, = 50, = nil, = 10, такая индексация не рекомендуется log ("clear") -- очистить лог log ("mode compact") -- компактный режим for i = 1, #arr do log (i, arr) end log() for i, value in ipairs(arr) do log (i, value) end -- А в этом примере разница заметна. 3й элемент пуст поэтому ipairs обошёл только элементы 1 и 2.
--lua local arr = { = 40, = 50, = 10} -- массив arr, элементы: = 40, = 50, = nil, = 10 log ("clear") -- очистить лог log ("mode compact") -- компактный режим for i, value in pairs(arr) do log (i, value) end -- pairs обходит все элементы массива, но не обязательно по порядку.
Условия
- Любое условие имеет вид:
- if … then
- …
- end
--lua local a = 13 if a == 13 then -- если переменная 'a' равна 13 log ("Условие выполнено, т. к. переменная a равна 13") end -- конец условия
--lua local a = 4 local b = 7 + a if b == 11 then -- если переменная 'b' равна 11 log ("Переменная b равна 11") end
--lua local x, y = 10, 30 if x + y == 40 then -- если сумма 'x' и 'y' равна 40 log ("+++") end
- Условия с else.
else выполняет другое действие, если условие c if не выполнилось.
--lua local x = 100 if x > 101 then -- если 'x' больше 101 log ("x больше 101") else -- иначе log ("x меньше 101") end
- Условия с elseif.
--lua local a = 15 local b = 0 if a > 20 then -- если а больше 20 b = 3 -- присвоить 3 переменной b elseif a < 20 then -- если же а меньше 20 b = 1 -- присвоить 1 переменной b else -- иначе b = -1 -- присвоить -1 переменной b end log (b)
- Несколько условий в одном if.
--lua local x = 5 local y = 7 if x == 5 and y == 7 then -- если x равен 5 и y равен 7 log ("+++") end
--lua local x = 5 local y = 7 if x == 5 or y == 10 then -- если x равен 5 или y равен 10 log ("+++") end
Обработка ошибок
Часто, если возникают ошибки, надо прекратить выполнение определенной функции. Можно, конечно, сделать множество проверок и вызывать «return», если что-то пошло не так. Но это увеличит объем кода. В Lua используется что-то наподобие исключений (exceptions).
Ошибки порождаются с помощью функции error(x). В качестве аргумента можно передать все, что угодно (то, что имеет отношение к ошибке — строковое описание, числовой код, объект, с которым произошла ошибка и т.д.)
Обычно после этой функции вся программа аварийно завершается. А это надо далеко не всегда. Если вы вызываете функцию, которая может создать ошибку (или ее дочерние функции могут создать ошибку), то вызывайте ее безопасно, с помощью pcall():
function f(x, y) ... if ... then error("failed to do somthing") end ... end status, err = pcall(f, x, y) -- f:функция, x-y: ее аргументы if not status then -- обработать ошибку err. В нашем случае в err находится текст ошибки end
Синтаксис
Привязка к окну: нет.
Работа со свернутым окном: да.
1-й тип (числовой цикл):
for i = iMin, iMax do end
Где:
i — числовая переменная-счётчик
iMin — начальное значение отсчета.
iMax — конечное значение отсчета (включительно).
шаг — шаг цикла (значение, которое при каждом цикле прибавляется к i). Может быть положительным или отрицательным. Необязателен. Если не указан, то равен 1.
iMin, iMax, шаг — вычисляются только один раз, перед выполнением цикла.
break — команда прерывания цикла. Передаёт управление на строку, находящуюся сразу за end.
Допустимо использование дробных чисел. Разделитель точка.
2-й тип (обход элементов массива/таблицы):
Условно можно разделить на 2 вида: pairs и ipairs.
ipairs — цикл перебирает все элементы массива/таблицы с целочисленными ключами в порядке возрастания начиная с единицы. Если значение элемента массива/таблицы nil, то выполняется выход из цикла.
pairs — используется для обхода вообще всех элементов массива/таблицы. Порядок обхода элементов непредсказуем, даже при использовании целочисленных ключей.
for i, value in ipairs(Array) do end
Где:
i — переменная, в которую записывается индекс элемента массива/таблицы.
value — переменная, в которую записывается значение элемента массива/таблицы.
Array — массив или таблица.
for i, value in pairs(Array) do end
Где:
i — переменная, в которую записывается ключ элемента массива/таблицы.
value — переменная, в которую записывается значение элемента массива/таблицы.
Array — массив или таблица.
Объекты = функции + таблицы
Раз мы можем сохранять функции в переменных, то и в полях таблиц тоже сможем. А это уже получаются как-бы-методы. Для тех, кто не знаком с ООП скажу, что основная его польза (по крайней мере в Lua) в том, что функции и данные, с которыми они работают находятся рядом — в пределах одного объекта. Для тех, кто знаком с ООП скажу, что классов здесь нет, а наследование прототипное.
Перейдем к примерам. Есть у нас объект, скажем, лампочка. Она умеет гореть и не гореть. Ну а действия с ней можно сделать два — включить и выключить:
lamp = { on = false } function turn_on(l) l.on = true end function turn_off(l) l.on = false end -- это просто функции для работы со структурой turn_on(lamp) turn_off(lamp)
А если лампочку сделать объектом, и функции turn_off и turn_on сделать полями объекта, то получится:
lamp = { on = false turn_on = function(l) l.on = true end turn_off = function(l) l.on = false end } lamp.turn_on(lamp) lamp.turn_off(lamp)
Мы вынуждены передавать сам объект лампочки в качестве первого аргумента, потому что иначе наша функция не узнает с какой именно лампочкой надо работать, чтобы сменить состояние on/off. Но чтобы не быть многословными, в Lua есть сокращенная запись, которую обычно и используют — lamp:turn_on(). Итого, мы уже знаем несколько таких упрощений синтаксиса:
lamp:turn_on() -- самая общепринятая запись lamp.turn_on(lamp) -- то с точки зрения синтаксиса это тоже правильно lamp(lamp) -- и это
Продолжая говорить о сокращениях, функции можно описывать не только явно, как поля структуры, но и в более удобной форме:
lamp = { on = false } -- через точку, тогда аргумент надо указывать function lamp.turn_on(l) l.on = true end -- через двоеточкие, тогда аргумент неявно задается сам, как переменная "self" -- "self" - и есть та лампочка, для которой вызвали метод function lamp:turn_off() self.on = false end
Интересно?
Переменные
- Объявление переменной и присваивание значения.
--lua local a = 3 -- объявить переменную "a" и присвоить ей значение 3 local b = 5 -- объявить переменную "b" и присвоить ей значение 5 log (a, b) -- вывести в лог значение переменной a и b
- Переменные чувствительны к регистру.
--lua local a = 1 local A = 2 log (a, A) -- a и A это разные переменные
- Можно присваивать значения нескольким переменным
--lua local a, b, c = 3, 1, 6 log (a, b, c)
- А так же менять их значения местами.
--lua local a, b = 10, 35 log (a, b) a, b = b, a -- присвоить переменной 'a' значение переменной 'b' и переменной 'b' значение 'a' log (a, b)
--lua local a, b, c, d = 11, 22, 33, 44 a, b, c, d = d, c, b, a log (a, b, c, d)
- Переменные могут содержать разные данные.
--lua local x = 2 -- содержит число local s = "это строка" -- любые символы, кроме чисел, заключаются в кавычки "текст" или 'текст' log (x, s)
6.1 – Основные функции
collectgarbage (])
opt
- «collect«: выполняет полный цикл сборки мусора. Это опция по умолчанию.
- «stop«: останавливает автоматическое выполнение сборщика мусора. Сборщик будет работать только когда явно вызывается, пока вызов не перезапустит его.
- «restart«: перезапускает автоматическое выполнение сборщика мусора.
- «count«: возвращает полный объем памяти, используемый Lua, в килобайтах. Значение имеет дробную часть, так что умножение его на 1024 даст точное число байт, используемых Lua (за исключением переполнений).
-
«step«: выполняет шаг по сборке мусора.
«Размером» шага управляет аргумент arg. С нулевым значением сборщик будет выполнять один основной (неделимый) шаг.
Для ненулевых значений сборщик будет выполнять свою работу так, как если бы такое количество памяти (в килобайтах) было выделено от Lua. Возвращает true, если шаг заканчивает цикл сборки мусора. - «setpause«: устанавливает аргумент arg как новое значение для паузы в работе сборщика мусора (смотрите ). Возвращает предыдущее значение для pause.
-
«setstepmul«: устанавливает аргумент arg как новое значение для множителя шага сборщика мусора (смотрите ).
Возвращает предыдущее значение шага. - «isrunning«: возвращает логическое значение, которое сообщает, запущен ли сборщик мусора (то есть, он не остановлен).
t
for i,v in ipairs(t) do body end
1,t2,t
t__pairsttnil
for k,v in pairs(t) do body end
t
Операторы языка
Набор условных операторов и циклов довольно типичен:
-- условные операторы (ветки else может не быть) if a == 0 then print("a is zero") else print("a is not zero") end -- сокращенная форма if/elseif/end (вместо switch/case) if a == 0 then print("zero") elseif a == 1 then print("one") elseif a == 2 then print("two") else print("other") end -- цикл со счетчиком for i = 1, 10 do print(i) end -- цикл с предусловием b = 5 while b > 0 do b = b - 1 end -- цикл с постусловием repeat b = b + 1 until b >= 5
ПОДУМАЙТЕ: что может означать цикл ?
В выражениях можно использовать такие вот операторы над переменными:
* присваивание: x = 0
* арифметические: +, -, *, /, % (остаток от деления), ^ (возведение в степень)
* логические: and, or, not
* сравнение: >, <, ==, <=, >=, ~= (не-равно, да-да, вместо привычного «!=»)
* конкатенация строк (оператор «..»), напр.: s1=»hello»; s2=»world»; s3=s1..s2
* длина/размер (оператор #): s=»hello»; a = #s (‘a’ будет равно 5).
* получение элемента по индексу, напр.: s
Битовых операций в языке долгое время не было, но в версии 5.2 появилась библиотека bit32, которая их реализует (как функции, не как операторы).
Между Lua и не-Lua
ВНИМАНИЕ: эту часть рекомендуется читать людям со знанием языка C. А если нам недостаточно функциональности стандартных библиотек? Если у нас есть наша программа на C, а мы хотим вызывать ее функции из Lua? Для этого есть очень простой механизм
А если нам недостаточно функциональности стандартных библиотек? Если у нас есть наша программа на C, а мы хотим вызывать ее функции из Lua? Для этого есть очень простой механизм.
Допустим, мы хотим создать свою функцию, которая возвращает случайное число (в Lua есть math.random(), но мы хотим поучиться). Нам придется написать вот такой код на C:
#include <lua.h> #include <lauxlib.h> #include <time.h> /* собственно, что делать при вызове `rand(from, to)` */ static int librand_rand(lua_State *L) { int from, to; int x; from = lua_tonumber(L, 1); /* первый параметр функции */ to = lua_tonumber(L, 2); /* второй параметр функции */ x = rand() % (to - from + 1) + from; lua_pushnumber(L, x); /* возвращаемое значение */ return 1; /* возвращаем только один аргумент */ } /* в Lua "rand" соответствует нашей функции librand_rand() */ static const luaL_reg R[] = { {"rand", librand_rand}, {NULL, NULL} /* конец списка экспортируемых функций */ }; /* вызывается при загрузке библиотеку */ LUALIB_API int luaopen_librand(lua_State *L) { luaL_openlib(L, "librand", R, 0); srand(time(NULL)); return 1; /* завершаемся успешно */ }
Т.е. Lua предоставляет нам функции для работы с типами данных, для получения аргументов функций и возврата результатов. Функций очень мало, и они довольно простые. Теперь мы собираем нашу библиотеку как динамическую, и можем использовать функцию rand():
random = require("librand") -- загружаем библиотеку print(random.rand(1, 100)) print(random.rand(0, 1))
А если мы хотим вызывать код, написанный на Lua из наших программ? Тогда наши программы должны создавать виртуальную машину Lua, в которой и будут выполняться Lua-скрипты. Это намного проще:
#include "lua.h" #include "lauxlib.h" int main() { lua_State *L = lua_open(); // создаем виртуальную машину Lua luaL_openlibs(L); // загружаем стандартные библиотеку luaL_dofile(L, "rand.lua"); // выполняем скрипт lua_close(L); // закрываем Lua return 0; }
Примеры простых циклов
--lua for i = 1, 3 do -- шаг не указан, по умолчанию равен 1 msg (i) end -- увидим: 1 2 3
--lua for i = 4, 8, 2 do -- шаг 2 msg ("Миша съел " .. i .. " яблок(а)") end -- увидим: 4 6 8
--lua -- назад, с шагом -1 local a = 4 local b = 2 local s = -1 for j = a, b, s do log ("Считаем назад: " .. j) end log ("Закончили счёт") -- увидим: 4 3 2 закончили
--lua -- вперед, с шагом 1, используем break for k = 2, 6 do log ("Считаем вперед: " .. k .. "A") if k == 4 then -- если переменная 'k' равна 4 break -- прервать цикл end log ("Считаем вперед: " .. k .. "Б") end log ("Закончили счёт") -- увидим: 2А 2Б 3А 3Б 4А Закончили
--lua -- цикл с нецелыми числами. for i = 0.1, 0.7, 0.15 do log (i) end
6.8 – Средства ввода/вывода
ioioio.stdinio.stdoutio.stderrnilnilerrno
io.open (filename )
modenilmode
- «r«: режим чтения (по умолчанию);
- «w«: режим записи;
- «a«: режим добавления;
- «r+«: режим обновления, все предыдущие данные сохраняются;
- «w+«: режим обновления, все предыдущие данные удаляются;
- «a+«: режим обновления с добавлением, предыдущие данные сохраняются, запись допускается только в конец файла.
modeb
l
for c in file:lines(1) do body end
file:read (...)
filenil
-
«n«: считывает число и возвращает его как число с плавающей запятой или целое число, следуя лексическим соглашениям Lua. (Число может иметь перед собой пробелы и знак.)
Этот формат всегда считывает самую длинную входную последовательность, которая является для числа допустимым префиксом; если этот префикс не формирует
допустимое число (например, пустая строка, «0x«, или «3.4e-«), он отбрасывается и функция возвращает nil. - «a«: считывает весь файл, начиная с текущей позиции. По окончании файла, возвращает пустую строку.
- «l«: считывает следующую строку, пропуская символ конца строки; возвращает nil по окончании файла. Это формат по умолчанию.
- «L«: считывает следующую строку, сохраняя символ конца строки (если он присутствует); возвращает nil по окончании файла.
-
number: считывает строку вплоть до указанного числа байт (number — число), возвращая nil по завершении файла.
Если number является нулем, то ничего не считывается и возвращается пустая строка, или nil по завершении файла.
lL
file:seek (])
offsetwhence
- «set«: базовое значение равно 0 (начало файла);
- «cur«: базовым значением является текущая позиция;
- «end«: базовым значением является конец файла;
seekseeknilwhence"cur"offsetfile:seek()file:seek("set")file:seek("end")
file:setvbuf (mode )
- «no«: нет буферизации; результат любой выходной операции появляется немедленно.
- «full«: полная буферизация; выходная операция выполняется только когда буфер полон, или когда буферы файла явно сбрасываются (смотрите ).
- «line«: строчная буферизация; выход буферизуется до тех пор, пока на выходе не появится символ «новая строка» или имеется любой ввод из некоторых специальных файлов (таких как терминальное устройство).
size