Lua является типичным процедурным языком программирования, предоставляющим широкие возможности для разработки. Это мощный и простой язык, обладающий всеми необходимыми выразительными средствами.
Будучи языком для создания расширений, Lua не имеет понятия основной программы, он работает в среде исполнения других программ, сокращенно называемых хост-программами. В данном случае хост-программой является программа GEDKeeper. Хост-программа позволяет запускать части кода (далее скрипты), написанные на Lua. Благодаря возможности расширения функциями хост-программы, Lua может применяться для решения широкого круга задач.
Lua является свободно распространяемым программным средством, поэтому предоставляется без каких-либо гарантий в соответствии с лицензией. Версия lua 5.1, которая описана в данном Руководстве, доступна на официальном сайте Lua www.lua.org.
Как и многие подобные Руководства, этот документ написан в формальном стиле. Для получения более подробной информации об особенностях применения языка рекомендуем обратиться к технической документации, доступной на официальном сайте Lua. Хорошим подспорьем в работе может оказаться книга Роберта Иерусалимского (Roberto Ierusalimschy) «Программирование на Lua», второе издание (Programming in Lua (Second Edition)).
В этой главе описываются элементы языка, способы их комбинирования и значение языковых конструкций.
Конструкции языка будут вводится с использованием расширенной BNF, где запись {a} означает 0 или более элементов a, а запись [a] означает его необязательное вхождение. Нетерминальные символы отображаются обычным шрифтом, ключевые слова выделяются жирным шрифтом kword, все остальные терминальные символы заключаются в апострофы `=?.
Именами (идентификаторами) в Lua могут быть любые строки из букв, цифр и символа подчеркивания, не начинающиеся с цифры. Это правило типично для большинства языков программирования. Идентификаторы используются для именования переменных и таблиц значений.
Следующие ключевые слова зарезервированы и не могут быть использованы в именах:
and break do else elseif
end false for function if
in local nill not or
repeat return then true until while
Lua является языком, чувствительным к регистру символов: and – ключевое слово, тогда как And и AND – два разных допустимых идентификатора. По соглашению, имена, начинающиеся с символа подчеркивания и записанные в верхнем регистре (например, _VERSION), зарезервированы для использования в качестве внутренних глобальных переменных, используемых Lua.
В следующих строках показаны другие допустимые символы:
+ * / % ^ / #
== ~= <= >= < > =
( ) { } [ ]
; : , . .. ...
Литеральные строки должны быть заключены в одинарные или двойные кавычки и могут содержать следующие С-подобные escape-последовательности: '\a' («звонок»), '\b' («забой»), '\f' («перевод страницы»), '\n' («перевод на новую строку»), '\r' («возврат каретки»), '\t' («горизонтальная табуляция»), '\v' («вертикальная табуляция»), '\\\"' («двойная кавычка»), and'\'' (апостроф [«одинарная кавычка»]). Кроме того, обратный слеш ставится перед концом строки в редакторе, когда для удобства набора длинные непрерывные строки записываются в несколько строк. Символ в строке также может быть представлен своим кодом с помощью escape-последовательности \ddd, где ddd- последовательность из не более чем трех цифр. (Заметим, что если после символа, записанного с помощью своего кода, должна идти цифра, то код символа в escape-последовательности должен содержать ровно три цифры). Строки в Lua могут содержать любые 8-битные значения, включая ноль, который записывается как '\0'.
Чтобы поместить одни двойные кавычки, символы новой строки, обратный слэш, или нулевой символ в строку, ограниченную двойными кавычками вы должны использовать escape-последовательности. Любой другой символ может быть напрямую включен в строку.
Числовая константа может быть записана с опциональной десятичной частью и опциональной десятичной экспонентой. Lua также принимает целые шестнадцатеричные константы, с префиксом 0x. Примеры правильных числовых констант
3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56
Комментарий начинается с двойного дефиса (--) везде за пределами строки. Если текст непосредственно после -- не содержит длинную открывающую скобку [, комментарий является коротким, который продолжается до конца строки. Иначе, это длинный комментарий, который продолжается пока не встретится закрывающая длинная скобка ]. Длинный комментарий часто встречается для временной деактивации кода.
Lua представляет собой язык с динамическим определением типов данных. Переменная языка может содержать значения любого типа. Возможности определения пользовательских типов данных отсутствуют. Все значения в Lua могут храниться в переменных, использоваться в качестве аргументов при вызове функций и возвращаться в виде результата их выполнения.
В Lua восемь основных типов: nil (неопределенный), boolean (логический), number (числовой), string (строковый), function (функция), userdata (пользовательские данные), thread (поток), и table (таблица). Nil - это тип значения nil [пустое значение], главное свойство которого – отличаться от всех остальных значений и обозначать отсутствие пригодного значения. К типу Boolean относятся значения false (ложь) и true (истина). Значения nil и false считаются ложными, любое другое значение считается истинным. К типу Number относятся вещественные числа (двойной точности с плавающей запятой). Тип String обозначает массивы символов. Строки Lua могут содержать любые 8 битные символы, включая ноль ('\0') (см. §2.1).
В Lua можно использовать функции, написанные на Lua или предоставляемые хост-программой (см. §2.5.8).
Тип userdata (пользовательские данные) позволяет хранить любые данных из хост-программы в переменных Lua. Значение этого типа является ссылкой на блок физической памяти и не имеет предопределенных операций в Lua, за исключением присваивания и проверки на равенство. Однако, используя метатаблицы, программист может определить операции над значениями этого типа (см. §2.8). Значения типа userdata не могут быть созданы или изменены непосредственно в Lua, это возможно только с помощью хост-программе. Такой подход гарантирует целостность данных, принадлежащих ведущей программе.
Тип table (таблица) определяет ассоциативные массивы. Такие массивы могут индексироваться не только числами, но и любыми значениями (за исключением nil). Таблица может содержать значения сразу нескольких типов (кроме nil). Таблицы представляют собой единственный механизм структурирования данных в Lua; они могут использоваться как простые массивы, таблицы символов, множества, поля записей, деревья и так далее. Для представления словарей Lua использует имя поля в качестве индекса таблицы. Представление в виде a.name считается тождественным представлению a["name"]. В Lua есть несколько способов создания таблиц (см. §2.5.7).
Индексы и значения полей таблицы могут быть любого типа (кроме nil). В частности, так как функции являются значениями встроенного типа, поля таблицы могут содержать и функции. Таким образом, таблицы могут хранить методы methods (см. §2.5.9).
Переменные типа table, function, thread и userdata не содержат самих данных, в них хранятся только ссылки на соответствующий объект. Присваивание, передача параметров и возврат результата из функции оперируют только ссылками на значения, эти операции никогда не ведут к созданию копий.
Библиотечная функция type возвращает строку, описывающую тип данного значения.
Lua обеспечивает автоматическое преобразование между строковыми и числовыми значениями в процессе выполнения. Любая арифметическая операция, применяемая к строке, пытается преобразовать эту строку в соответствующее число по обычным правилам приведения. Когда же число используется там, где ожидается строка, это число преобразуется в строку в произвольном подходящем формате. Так что для получения какого-то конкретного представления числа в строке необходимо использовать функцию format из библиотеки работы со строками (см. string. format ).
Переменные используются для хранения значений в процессе выполнения программы. В Lua есть три вида переменных: глобальные, локальные и поля таблиц.
Отдельный идентификатор может обозначать глобальную или локальную переменную (либо формальный параметр функции, что является частным случаем локальной переменной) :
var ::= Name
Где Name – идентификатор, определяемый в соответствии с §2.1.
Любая переменная считается глобальной, если она явно не объявлена как локальная (см. §2.4.7). Локальные переменные существуют в лексическом контексте: локальные переменные доступны функциям, определенным внутри этого контекста (см. §2.6).
До первого явного присвоения значением переменной является nil.
Квадратные скобки используются для доступа к элементу таблицы по индексу:
var ::= prefixexp '[' exp ']'
Запись var.Name аналогична записи var["Name"]:
var ::= prefixexp '.' Name
В Lua поддерживается стандартный набор операторов, почти как в Pascal или C. Он состоит из операторов присваивания, операторов управления потоком исполнения, вызова функций и описания переменных.
Единица исполнения Lua называется chunk (порция). Порция – это любая последовательность операторов Lua. Операторы в порции могут разделяться точкой с запятой:
chunk ::= {stat [';']}
Пустого оператора в языке нет, поэтому выражение ';;' не допустимо.
Lua воспринимает порцию как неименованную функцию с произвольным набором параметров (см. §2.5.9). Порция может определять локальные переменные и возвращать значения.
Блок это список операторов; синтаксически блок тождественно равен порции (chunk) :
block ::= chunk
Блок операторов может быть явно ограничен, таким образом представляется составной оператор:
stat ::= do block end
С помощью составных операторов можно ограничивать области видимости локальных переменных. Также составные операторы используются в циклах и условном операторе (см. §2.4.4).
Lua поддерживает параллельное присваивание. В общем случае, оператор присваивания выглядит как список переменных, символ ‘=’ и список выражений. Элементы списков указываются через запятую:
stat ::= varlist1 '=' explist1
varlist1 ::= var {',' var}
explist1 ::= exp {',' exp}
Выражения (exp) рассмотрены в §2.5.
Перед выполнением присваивания список переменных согласовывается по длине со списком выражений. Если список справа длиннее, то его лишние элементы просто отбрасываются. Если короче, то недостающие позиции дополняются значениями nil. Если список операторов оканчивается вызовом функции, то перед согласованием все возвращаемые оттуда значения вставляются в правый список (за исключением случаев, когда вызов взят в скобки; смотрите §2.5).
Перед выполнением присваивания вычисляется значение всех выражений. Код
i = 3
i, a[i] = i+1, 20
означает, что переменной a[3] присваивается значение 20, потому что i в выражении a[i] имеет то же самое значение, что и в момент вычисления выражения i+1. Аналогично, строка
x, y = y, x
является простым способом обмена значениями двух переменных (при «традиционном» способе требуется дополнительная переменная).
Операторы if, while, и repeat имеют обычное значение и знакомый синтаксис:
stat ::= while exp do block end
stat ::= repeat block until exp
stat ::= if exp then block {elseif exp then block} [else block] end
В Lua также имеется выражение for в двух вариантах (см. §2.4.5).
Логическое выражение в управляющих конструкциях может возвращать любое значение. Значения false и nil считаются ложными. Все остальные значения считаются истинными (в том числе значение 0 и пустая строка!).
Цикл repeat–until оканчивается условием, идущим следом за until, поэтому в условии можно ссылаться на локальные переменные, описанные внутри цикла.
Выражение return используется для того, чтобы возвратить значения из функции или порции. Синтаксис оператора return позволяет функции или порции вернуть несколько значений:
stat ::= return [explist1]
Оператор break используется для досрочного выхода из циклов while, repeat и for:
stat ::= break
Break прерывает цикл, в теле которого встречается, внешние циклы продолжают выполнение.
Return (или break) должен быть последним оператором в блоке (иначе следующие за ним операторы никогда не выполнятся). Если действительно необходимо вставить return или break в середину блока, то следует применить составной оператор, например, do return end и do break end.
Оператор for допускает простую и расширенную формы записи.
В простой форме for выполняет блок кода до тех пор, пока переменная цикла, изменяющаяся в арифметической прогрессии, не достигнет установленного порога.
stat ::= for Name ' = ' exp1 ',' exp2 [', ' exp3] do block end
block повторяется для переменной цикла name начиная со значения выражения exp1, до тех пор пока выполняется выражение exp2 с шагом выражения exp3.
Таким образом, запись
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
Обратите внимание, что:
Расширенная форма оператора 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
Заметим, что
Для создания побочных эффектов может быть полезен вызов функций, используемый в качестве оператора:
stat ::= functioncall
В этом случе все возвращаемые значения отбрасываются. Вызовы функций рассматриваются в §2.5.8.
Локальные переменные могут быть объявлены где угодно внутри блока. Объявление может включать инициализацию:
stat ::= local namelist ['=' explist1]
Инициализация обладает всеми свойствами операции присваивания (в том числе параллельностью) (см. §2.4.3). По умолчанию все переменные инициализируются значением nil.
Порция является блоком (см. §2.4.1), поэтому локальные переменные могут быть объявлены вне любого явно заданного блока. Областью действия таких локальных переменных являются границы порции.
Правила видимости для локальных переменных рассмотрены в §2.6.
Выражениями в Lua являются следующие конструкции:
exp ::= prefixexp
exp ::= nil | false | true
exp ::= Number
exp ::= String
exp ::= function
exp ::= tableconstructor
exp ::= '...'
exp ::= exp binop exp
exp ::= unop exp
prefixexp ::= var | functioncall | '(' exp ')'
Числа и символьные строки рассмотрены в §2.1; переменные - в §2.3; описания функций - в §2.5.9; вызовы функций - в §2.5.8; конструкторы таблиц - в §2.5.7. Неявные аргументы, обозначаемые ‘...', могут использоваться только внутри соответственно заданной функции; смотрите §2.5.9.
К бинарным операциям (binop в формальном определении выражения) относятся арифметические (см. §2.5.1), операции сравнения (§2.5.2), булевские (§2.5.3) и операции конкатенации (смотреть §2.5.4). Унарными являются унарный минус (§2.5.1), отрицание not (§2.5.3) и операция получения длины # (§2.5.5).
Результат вызова функций и неявные параметры могут содержать несколько значений. Если при этом они используются в качестве оператора (§2.4.6) (только для функций), то все возвращаемые значения отбрасываются. Если это последний (или единственный) элемент в списке выражений, то никакая корректировка не проводится (если вызов не взят в скобки). В остальных случаях Lua приводит возвращаемый список к одному элементу, отбрасывая все значения кроме первого.
Далее несколько примеров:
f() -- результат функции отбрасывается
g(f(), x) -- берется первое значение из списка - результата вызова f()
g(x, f()) -- g получает x и все значения, полученные из f()
a,b,c = f(), x -- берется первый элемент результата вызова f()(и c получает nil)
a,b = ... -- a получает первый параметр из ..., b - второй (причем а и b могут получить nil, если в качестве неявных параметров ничего не передано)
a,b,c = x, f() -- 2 результата из f()
a,b,c = f() -- 3 результата из f()
return f() -- возвращает все значения из f()
return ... -- возвращает все полученные неявные аргументы
return x,y,f() -- вернет a, b и все, что вернет f()
{f()} -- создаст список со всем результатами вызова f()
{...} -- создаст список со всеми неявными параметрами
{f(), nil} -- 1 результат из f()
Выражение, заключенное в скобки, всегда возвращает только одно значение. Таким образом,
(f(x,y,z))
всегда даст единственное значение, даже если f возвращает несколько.
(Значение (f(x,y,z)) это первое значение,
полученное из f, или nil, если f не возвращает значений.)
Lua поддерживает обычные арифметические операции: двоичные + (сложение), - (вычитание), * (умножение), / (деление), % (остаток от деления), и ^ (возведение в степень); а также унарный минус - (изменение знака числа). Если операнды являются числами или строками (которые могут быть преобразованы в числа §2.2.1), то операции выполняются обычным образом. Возведение в степень работает для любого показателя степени. Например, x^(-0.5) подсчитывает величину, обратную квадратному корню из x.
Операции сравнения в Lua:
== ~= < > <= >=
Эти операции всегда возвращают false или true.
Сравнение на равенство (==) сначала сравнивает типы операндов. Если типы различны, то результатом будет false. Иначе сравниваются значения операндов. Числа и строки сравниваются обычным способом. Объекты (таблицы, пользовательские данные, потоки и функции) сравниваются по ссылке: два объекта считаются равными, только если они являются одним и тем же объектом. Создаваемый объект (таблица, пользовательские данные, поток или функция) не может быть равен ни одному из уже существующих.
Правила преобразования из §2.2.1 НЕ работают в сравнениях на равенство. Например, "0"==0 вернет false, а t[0] и t["0"] обозначают различные записи в таблице.
Оператор ~= прямо противоположен оператору равенства (==).
Операторы сравнения на больше-меньше работают следующим образом. Если оба параметра - числа, то они сравниваются как обычно. Если оба параметра строки, то их значения сравниваются в соответствии с лексикографическим порядком. Во всех остальных ситуациях будет вызван метаметод (в данном руководстве не рассматривается).
В Lua это операции and (и), or (или), и not (не). Так же, как и в управляющих конструкциях (§2.4.4), все логические операции рассматривают false и nil как ложь, а все остальное как истину.
Операция отрицания not всегда возвращает false или true. Операция конъюнкции and возвращает свой первый параметр, если его значение false или nil; в противном случае and возвращает второй параметр. Оператор дизъюнкции or возвращает первый параметр, если его значение отлично от nil и false; в противном случае or возвращает второй параметр. Оба оператора вычисляют второй операнд только в случае необходимости.
Примеры:
10 or 20 --> 10
10 or error() --> 10
nil or "a" --> "a"
nil and 10 --> nil
false and error() --> false
false and nil --> false
false or nil --> nil
10 and 20 --> 20
(В данном руководстве, --> указывает на результат выражения.)
Оператор конкатенации (соединения) строк в Lua обозначается двумя точками ('..'). Если оба операнда являются строками или числами, то они будут преобразованы в строки согласно правилам §2.2.1. Иначе будет вызван метаметод (в данном руководстве не рассматривается).
Операция получения длины обозначается унарным #. В результате применения операции к строке возвращается количество байт (в обычном понимании это длина строки, в которой каждый символ занимает 1 байт).
Длиной таблицы t считается любой целый индекс n такой, что t[n] не равен nil, а t[n+1] равно nil. Кроме того, если t[ 1] равен nil, то #t = 0. Для регулярных массивов от 1 до n, не содержащих значений nil, длиной является n, то есть индекс последнего значения. Если в массиве присутствуют "дыры" (т.е., значения nil между ненулевыми значениями), то значением #t является индекс элемента, непосредственно предшествующего элементу nil (поэтому любое значение nil по сути означает конец массива).
Приоритет операций Lua показан на таблице ниже. Самым высоким приоритетом обладает операция возведения в степень, далее по убыванию:
or
and
< > <= >= ~= ==
..
+ -
* / %
not # - (unary)
^
Как обычно, для изменения порядка вычисления выражений вы можете использовать скобки. Конкатенация ('..') и возведение в степень ('^') - правоассоциативные операторы. Все остальные бинарные операторы левоассоциативные.
Конструкторы таблиц тоже относятся к выражениям. Обработка любого встречающегося в коде конструктора ведет к созданию новой таблицы. С помощью конструкторов можно создать как пустые, так и частично либо полностью заполненные таблицы. Полное описание синтаксиса конструкторов:
tableconstructor::= '{' [fieldlist] '}'
fieldlist::= field {fieldsep field} [fieldsep]
field::= '[' exp ']' '=' exp | Name '=' exp | exp
fieldsep::= ',' | ';'
Каждое поле вида [exp1] = exp2 добавляет в новую таблицу значение exp2 с ключом exp1. Поле вида name = exp эквивалентно ["name"] = exp. Поле вида exp эквивалентно [i] = exp, где i – целочисленный автоинкрементный счетчик, начинающийся с 1. Поля в других форматах не оказывают влияния на этот счетчик. Например,
a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
эквивалентно
do
local t = {}
t[f(1)] = g
t[1] = "x"
t[2] = "y"
t.x = 1
t[3] = f(x)
t[30] = 23
t[4] = 45
a = t
end
Если последнее поле в списке задано в форме exp, и exp – это вызов функции или неопределенный список параметров, то все значения, возвращаемые этим выражением, последовательно включаются в этот список (§2.5.8). Чтобы этого избежать, необходимо заключить вызов функции (или список неопределенных параметров) в скобки (§2.5).
Список полей может оканчиваться разделителем, что улучшает читабельность машинно-генерируемого кода.
Вызовы функций в Lua имеют следующий синтаксис:
functioncall ::= prefixexp args
В вызове функции сначала вычисляются префиксное выражение и аргументы. Если значение префиксного выражения имеет тип function, то эта функция будет вызвана с указанными аргументами. В противном случае вызывается метаметод (в данном руководстве не рассматривается).
Форма записи
functioncall ::= prefixexp ':' Name args
может использоваться для вызова "методов". Запись v:name (args) синтаксически аналогична записи v.name ( v,args), только v вычисляется один раз.
Аргументы описываются следующим образом:
args ::= '(' [explist1] ')'
args ::= tableconstructor
args ::= String
Все выражения вычисляются перед вызовом. Вызов в форме f{fields} синтаксически аналогичен f ({ fields}); то есть список аргументов является по сути новой таблицей. Вызов в форме f'string' (или f"string" или f[[string]]) синтаксически равен f('string' ); в данном случае список аргументов - единственная символьная строка.
Исключением в довольно свободном синтаксисе Lua является правило, по которому нельзя переходить на новую строку непосредственно перед символом '(' в вызове функции. Это ограничение позволяет избежать некоторой двусмысленности в языке. Если вы напишите
a = f
(g).x(a)
Lua трактует эту запись как выражение a = f ( g).x(a). Поэтому, если вам нужно 2 выражения, вы должны добавить точку с запятой между ними. Если вы действительно хотите вызвать f, вы необходимо убрать переход на новую строку перед (g).
Вызов в форме return functioncall называется концевым вызовом. Lua также поддерживает концевой вызов «себя» (или рекурсивный концевой вызов): в этом случае вызванная функция использует стек вызывающей функции. Поэтому количество вложенных концевых вызовов может быть любым. Заметим только, что концевой вызов стирает отладочную информацию о вызывающей функции. Синтаксис концевого вызова допускает только единичный вызов функции после оператора return. Таким образом, return вернет в точности тот результат, что вернет вызов функции. Ни один из представленных ниже примеров не является допустимым концевым вызовом:
return (f(x)) -- список-результат обрезается
return 2 * f(x) -- удвоение результата функции
return x, f(x) -- возвращается несколько значений
f(x); return -- результат вызова отбрасывается
return x or f(x) -- список-результат обрезается
Синтаксис объявления функций:
function ::= function funcbody
funcbody ::= '(' [parlist1] ')' block end
Или в упрощенном виде
stat ::= function funcname funcbody
stat ::= local function Name funcbody
funcname ::= Name {'.' Name} [':' Name]
Выражение
function f () body end
транслируется в
f = function () body end
Выражение
function t.a.b.c.f () body end
транслируется в
t.a.b.c.f = function () body end
Выражение
local function f () body end
транслируется в
local f; f = function () body end
а не в
local f = function () body end
(Разница проявится в том случае, если в теле функции используется имя этой функции, например при рекурсивном вызове)
Объявление функции является выполняемым выражением, его результатом будет значение типа function. Когда Lua прекомпилирует порцию, тела всех упоминающихся в ней функций также прекомпилируются. Таким образом, всякий раз, когда Lua обрабатывает объявление функции, функция уже конкретизирована (или замкнута). Этот конкретный экземпляр функции (или замыкание) и является конечным значением выражения «объявление функции». Различные экземпляры одной и той же функции могу ссылаться на различные внешние локальные переменные и иметь различные таблицы окружения.
Параметры функции фактически являются локальными переменными, которые инициализированы входными значениями:
parlist1 ::= namelist [',' '...'] | '...'
В момент вызова функции длина списка передаваемых параметров приводится в соответствие спецификации, если это не функция с неопределенным количеством параметров. Для функций с неопределенным количеством параметров такая коррекция не проводится; все входные параметры попадают в функцию в виде неопределенного выражения, которое также обозначается с тремя точками. Значением этого выражения является список всех полученных входных параметров, как в случае множественного результата функции. Если неопределенное выражение используется внутри другого выражения или в середине списка выражений, то его значение-список урезается до одного элемента. Если это выражение стоит в конце списка выражений, урезания не происходит (если конечно вызов не заключен в круглые скобки).
Рассмотрим следующие объявления:
function f(a, b) end
function g(a, b, ...) end
function r() return 1,2,3 end
Пример отображения входных значений на параметры функции:
ВЫЗОВ ПАРАМЕТРЫ
f(3) a=3, b=nil
f(3, 4) a=3, b=4
f(3, 4, 5) a=3, b=4
f(r(), 10) a=1, b=10
f(r()) a=1, b=2
g(3) a=3, b=nil, ... --> (ничто)
g(3, 4) a=3, b=4, ... --> (ничто)
g(3, 4, 5, 8) a=3, b=4, ... --> 5 8
g(5, r()) a=5, b=1, ... --> 2 3
Результаты возвращаются из функции оператором return (см. §2.4.4). Если управление достигает конца функции, а оператор return не встретился, то функция завершается и ничего не возвращает.
Синтаксис с двоеточием ‘:’ используется для определения методов. Эти функции неявно получают параметр self в качестве первого аргумента. Таким образом, выражение
function t.a.b.c:f (params) body end
аналогично
t.a.b.c.f = function (self, params) body end
Lua язык с лексическим разграничением областей видимости. Область видимости переменной начинается первым выражением после ее объявления и действует до конца блока, в котором это объявление встречается. Рассмотрим следующий пример:
x = 10 -- глобальная переменная variable
do -- начало блока
local x = x -- объявление локальной переменной
print(x) --> 10
x = x+1
do -- начало вложенного блока
local x = x+1 -- другая локальная 'x'
print(x) --> 12
end
print(x) --> 11
end
print(x) --> 10 (глобальная переменная)
Отметим, что в объявлении local x = x локальная переменная объявляется еще не в области своей видимости, поэтому присваивается именно внешняя переменная.
В соответствии с правилами лексического разграничения областей видимости, локальные переменные доступны в функциях, определенных внутри их области видимости. Локальная переменная, используемая в таких функциях, называется внешней локальной переменной (по отношению к определенной внутри ее области видимости функции).
Обработка каждого объявления local ведет к созданию новой локальной переменной. Рассмотрим следующий пример:
a = {}
local x = 20
for i=1,10 do
local y = 0
a[i] = function () y=y+1; return x+y end
end
Цикл создает 10 экземпляров функции, в которых используются различные переменные y и один и тот же x.
Поскольку Lua является языком расширений, работа Lua начинается с момента вызова в хост-программе функции из Lua-библиотеки (lua_pcall). При возникновении ошибки в процессе компиляции или выполнения Lua управление возвращается в хост-программу, где и осуществляется ее обработка (например, вывод сообщения о ошибке).
Lua-код может явно генерировать ошибку, вызывая функцию error. Если вам нужно перехватывать ошибки в самом Lua, вы можете использовать функцию pcall.
Lua осуществляет автоматическое управление памятью. Это означает, что вам не нужно думать о выделении памяти при создании новых объектов и ее освобождении, когда объект становится ненужным. Lua время от времени автоматически запускает процедуру сборки мусора для удаления устаревших объектов (то есть объектов, которые более недоступны из Lua). Сборщик мусора обрабатывает все объекты Lua: таблицы, данные типа userdata, функции, потоки и строки.
Типы данных:
void - пустой аргумент или результат функции;
int - целочисленный аргумент или результат функции;
string - строковый аргумент или результат функции;
boolean - логический аргумент или результат функции;
Внимание: Все списки базы данных нумеруются от нуля, поэтому для перебора всех записей базы данных следует использовать, к примеру, такую конструкцию:
for i = 0, get_records_count() - 1 do -- т.е. число элементов "-1"
...
end
Все действия над структурами данных базе выполняются посредством указателей (pointer) на эти структуры. Указатель - специальная переменная, указывающая программе на ту или иную структуру в памяти.
Указатели на структуры имеют следующие типы: