
Содержание
- Краткая справка
- Преимущества и недостатки
- Среды разработки
- Полезные ссылки
- Краткая справка
- Преимущества и недостатки
- Среды разработки
- Содержание
- Lua? Что это? [ править ]
- Зачем? [ править ]
- Что надо для того, чтобы читать дальше? [ править ]
- Первые впечатления [ править ]
- Указания языка [ править ]
- Виды данных [ править ]
- Таблицы [ править ]
- Функции [ править ]
- Объекты = таблицы + функции [ править ]
- Расширение функциональности [ править ]
- Области видимости [ править ]
- Обработка ошибок [ править ]
- Уставные библиотеки [ править ]
- Между Lua и не-Lua [ править ]
Краткая справка
Lua бы придуман в 1993 году в Католическом университете Рио-де-Жанейро. Название переводится с португальского, как Луна, причем создатели убедительно просят не писать LUA, чтобы, не дай Бог, кто-нибудь не принял название за аббревиатуру. Является мультипарадигмальным скриптовым языком, использующим прототипную модель ООП.
Типизация здесь динамическая, а для реализации наследования используются метатаблицы, то есть это прекрасный инструмент для расширений возможностей вашего продукта. Причем из-за своей компактности он пригоден для использования практически на любой платформе. Посудите сами: tarball Lua 5.3.4 весит всего 296 килобайт (в “разжатом” виде — 1.1 мегабайт), интерпретатор (написанный на C) для Linux — от 182 до 246 килобайт, а стандартный набор библиотек — ещё 421 килобайт.
По внешнему виду, да и возможностям Lua похож на очередную попытку переделать JavaScript, если бы не тот факт, что последний появился на два года позднее. Смотрите сами:
Начнем с традиционного:
Согласитесь, знакомо и не слишком информативно. Более интересный пример с точки зрения знакомства с Lua — вычисление факториала введенного числа:
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("enter a number:")
a = io.read("*number") — read a number
print(fact(a))
Все предельно понятно. Кстати, в Lua поддерживается параллельное присваивание:
И в заключении довольно простой пример с использованием библиотек:
#include
#include
#include
#include
#include
int main (void) <
char buff[256];
int error;
lua_State *L = lua_open(); /* opens Lua */
luaopen_base(L); /* opens the basic library */
luaopen_table(L); /* opens the table library */
luaopen_io(L); /* opens the I/O library */
luaopen_string(L); /* opens the string lib. */
luaopen_math(L); /* opens the math lib. */
while (fgets(buff, sizeof(buff), stdin) != NULL) <
error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
lua_pcall(L, 0, 0, 0);
if (error) <
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
>
>
Преимущества и недостатки
Итак, чем же хорош Lua?
Во-первых, как уже было отмечено, своей компактностью, а вкупе с тем, что исходники написаны на С, вы получаете полное взаимодействие с одним из популярнейших языков на планете и широкий спектр доступных платформ.
Во-вторых, он быстрый. Если взглянуть на сравнительную характеристику с другими языками, то можно заметить, что хоть Lua и не укладывает на лопатки C или Python, но в некоторых тестах показывает отличные результаты.
В-третьих, он очень удобен для изучения даже не самыми опытными программистами. Наверняка даже те, кто просто знает английский язык, поняли минимум 80% описанного выше кода и без проблем смогут воспроизвести.
Четвертый аргумент — у вас не возникнет никаких проблем с поиском информации. У Lua есть много полезной информации непосредственно на официальном сайте. Кроме того, очень недурно развито сообщество на StackOverFlow и IRC-чате, а в США разработчики и создатели так и вовсе встречаются каждый год.
Любителей современных тенденций привлечет тот факт, что на Lua можно писать функциональный код.Да что там, если вы хотя бы пару недель уделите программированию на Lua, то наверняка найдёте ещё не один десяток плюсов.
Впрочем, не существует языков без недостатков, но у Lua они носят локальный характер. Так, например, язык по умолчанию не поддерживает Unicode, но это исправляется с использованием специальной ICU библиотеки. Или ограниченные возможности обработки ошибок и исключений, хотя многие сочтут это за благо. Или необходимость ставить оператор return исключительно последним в блоке, но опять-таки для многих это естественное правило хорошего кода.
Хотите стать веб-разработчиком? Тогда вам на наш курс обучения web-разработке!
Среды разработки
LDT (Lua Development Tools) для Eclipse — расширение для одной из наиболее популярных IDE;
ZeroBrane Studio — специализированная среда, написанная на Lua;
Decoda — не самая популярная кроссплатформенная IDE, но в качестве альтернативы подойдет;
SciTE — хороший редактор, полноценно поддерживающий Lua;
WoWUIDesigner — угадайте, для какой игры эта среда помогает обрабатывать скрипты, в том числе на Lua?

Полезные ссылки
http://www.lua.org/home.html — официальный сайт со всей необходимой информацией, учебником, книгами, документацией и даже есть немного специфического юмора;
http://tylerneylon.com/a/learn-lua/ — отличная обучалка от Tyler Neylon. Подойдет программистам с опытом, кто хорошо знает английский язык (впрочем, со словарем тоже не возникнет больших проблем) и просто желает расширить свой кругозор;
https://zserge.wordpress.com/2012/02/23/lua-за-60-минут/ — основы Lua за 60 минут от явно неравнодушного к этому языку программиста. На русском языке;
https://youtube.com/watch?v=yI41OL0-DWM — видеоуроки на YouTube, которые помогут вам наглядно разобраться с настройкой IDE и базовыми принципами языка.
Наш сегодняшний гость — настоящий боец скрытого фронта. Вы могли видеть его в играх (World of Warcraft, Angry Birds, X-Plane, S.T.A.L.K.E.R.) или продуктах компании Adobe (Lightroom), но даже не задумывались о его существовании. Между тем этому языку уже почти 25 лет и всё это время он незаметно делал нашу виртуальную жизнь чуть лучше.

Краткая справка
Lua бы придуман в 1993 году в Католическом университете Рио-де-Жанейро. Название переводится с португальского, как Луна, причем создатели убедительно просят не писать LUA, чтобы, не дай Бог, кто-нибудь не принял название за аббревиатуру. Является мультипарадигмальным скриптовым языком, использующим прототипную модель ООП.
Типизация здесь динамическая, а для реализации наследования используются метатаблицы, то есть это прекрасный инструмент для расширений возможностей вашего продукта. Причем из-за своей компактности он пригоден для использования практически на любой платформе. Посудите сами: tarball Lua 5.3.4 весит всего 296 килобайт (в “разжатом” виде — 1.1 мегабайт), интерпретатор (написанный на C) для Linux — от 182 до 246 килобайт, а стандартный набор библиотек — ещё 421 килобайт.
По внешнему виду, да и возможностям Lua похож на очередную попытку переделать JavaScript, если бы не тот факт, что последний появился на два года позднее. Смотрите сами:
Начнем с традиционного:
Согласитесь, знакомо и не слишком информативно. Более интересный пример с точки зрения знакомства с Lua — вычисление факториала введенного числа:
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("enter a number:")
a = io.read("*number") — read a number
print(fact(a))
Все предельно понятно. Кстати, в Lua поддерживается параллельное присваивание:
И в заключении довольно простой пример с использованием библиотек:
#include
#include
#include
#include
#include
int main (void) <
char buff[256];
int error;
lua_State *L = lua_open(); /* opens Lua */
luaopen_base(L); /* opens the basic library */
luaopen_table(L); /* opens the table library */
luaopen_io(L); /* opens the I/O library */
luaopen_string(L); /* opens the string lib. */
luaopen_math(L); /* opens the math lib. */
while (fgets(buff, sizeof(buff), stdin) != NULL) <
error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
lua_pcall(L, 0, 0, 0);
if (error) <
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
>
>
Преимущества и недостатки
Итак, чем же хорош Lua?
Во-первых, как уже было отмечено, своей компактностью, а вкупе с тем, что исходники написаны на С, вы получаете полное взаимодействие с одним из популярнейших языков на планете и широкий спектр доступных платформ.
Во-вторых, он быстрый. Если взглянуть на сравнительную характеристику с другими языками, то можно заметить, что хоть Lua и не укладывает на лопатки C или Python, но в некоторых тестах показывает отличные результаты.
В-третьих, он очень удобен для изучения даже не самыми опытными программистами. Наверняка даже те, кто просто знает английский язык, поняли минимум 80% описанного выше кода и без проблем смогут воспроизвести.
Четвертый аргумент — у вас не возникнет никаких проблем с поиском информации. У Lua есть много полезной информации непосредственно на официальном сайте. Кроме того, очень недурно развито сообщество на StackOverFlow и IRC-чате, а в США разработчики и создатели так и вовсе встречаются каждый год.
Любителей современных тенденций привлечет тот факт, что на Lua можно писать функциональный код.Да что там, если вы хотя бы пару недель уделите программированию на Lua, то наверняка найдёте ещё не один десяток плюсов.
Впрочем, не существует языков без недостатков, но у Lua они носят локальный характер. Так, например, язык по умолчанию не поддерживает Unicode, но это исправляется с использованием специальной ICU библиотеки. Или ограниченные возможности обработки ошибок и исключений, хотя многие сочтут это за благо. Или необходимость ставить оператор return исключительно последним в блоке, но опять-таки для многих это естественное правило хорошего кода.
Хотите стать веб-разработчиком? Тогда вам на наш курс обучения web-разработке!
Среды разработки
LDT (Lua Development Tools) для Eclipse — расширение для одной из наиболее популярных IDE;
ZeroBrane Studio — специализированная среда, написанная на Lua;
Decoda — не самая популярная кроссплатформенная IDE, но в качестве альтернативы подойдет;
SciTE — хороший редактор, полноценно поддерживающий Lua;
WoWUIDesigner — угадайте, для какой игры эта среда помогает обрабатывать скрипты, в том числе на Lua?
Скрипты на языке Lua
Написанный на Lua скрипт не имеет какой-либо специальной функции, с которой начиналось бы его выполнение. Скрипт можно рассматривать просто как набор команд (инструкций), который выполняется, начиная с первой инструкции.
Скрипт может быть как очень простым, состоящим всего из одной команды, так и весьма сложным, содержащим десятки, сотни и даже тысячи инструкций. Следующие друг за другом инструкции могут разделяться точкой с запятой (;). Однако это требование не является обязательным, поэтому весь приведённый ниже код является корректным с точки зрения синтаксиса:
Работа с переменными в Lua
Переменные используются для хранения значений в процессе выполнения скрипта.
Имена переменных в Lua
Именами (идентификаторами) переменных в Lua могут быть любые последовательности из букв, цифр и символа подчеркивания, начинающиеся не с цифры.
Язык Lua различает регистр символов, поэтому abc, Abc, ABC являются различными именами.
В таблице ниже приведены слова, которые зарезервированы языком Lua и не могут использоваться в именах переменных:
and break do else elseif
end false for function if
in local nil not or
repeat return then true until
Кроме того, все имена, начинающиеся с символа подчеркивания, за которым идут заглавные буквы (например, _VERSION) также являются зарезервированными.
Какие переменные бывают в Lua?
Переменные в Lua могут быть глобальными и локальными. Если переменная не объявлена явно как локальная, она считается глобальной.
Глобальные переменные Lua
Глобальная переменная появляется в момент присваивания ей первого значения. До присваивания первого значения обращение к глобальной переменной даёт nil.
MsgBox(tostring (g)) —> nil
MsgBox(tostring (g)) —> 1
Глобальная переменная существует до тех пор, пока существует среда исполнения скрипта и доступна любому Lua-коду, выполняемому в этой среде.
При необходимости удалить глобальную переменную можно явным образом, просто присвоив ей значение nil.
g = 1 — создаем глобальную переменную g со значением 1
g = nil — удаляем глобальную переменную g
MsgBox(tostring (g)) —> nil
Все глобальные переменные являются полями обычной таблицы, называемой глобальным окружением. Эта таблица доступна через глобальную переменную _G. Поскольку полями глобального окружения являются все глобальные переменные (включая саму _G), то _G._G == _G.
Локальные переменные Lua
Любые локальные переменные должны быть объявлены явно с использованием ключевого слова local. Объявить локальную переменную можно в любом месте скрипта. Объявление может включать в себя присваивание переменной начального значения. Если значение не присвоено, переменная содержит nil.
local a — объявляем локальную переменную a
local b = 1 — объявляем локальную переменную b, присваиваем ей значение 1
local c, d = 2, 3 — объявляем локальные переменные c и d, присваиваем им значения 2 и 3
Область видимости локальной переменной начинается после объявления и продолжается до конца блока.
Областью видимости переменной называется участок кода программы, в пределах которого можно получить доступ к значению, хранящемуся в данной переменной.
Под блоком понимается:
тело управляющей конструкции (if-then, else, for, while, repeat);
фрагмент кода, заключённый в ключевые слова do. end.
Если локальная переменная определена вне какого-либо блока, её область видимости распространяется до конца скрипта.
a = 5 — глобальная переменная a
local i = 1 — переменная i локальна в пределах скрипта
while i 1, 4, 9, 16, 25
MsgBox(a) —> 5 (здесь обращение к глобальной a)
local a — переменная а локальна внутри then
MsgBox(a) —> 5 (здесь обращение к глобальной a)
local a = 20 — переменная а локальна внутри do-end
MsgBox(a) —> 5 (здесь обращение к глобальной a)
Когда возможно, рекомендуется использовать локальные переменные вместо глобальных. Это позволит избежать «засорения» глобального пространства имён и обеспечит лучшую производительность (поскольку доступ к локальным переменным в Lua выполняется несколько быстрее, чем к глобальным).
Типы данных Lua
Какие типы данных поддерживает язык Lua?
Lua поддерживает следующие типы данных:
1. Nil (ничего). Соответствует отсутствию у переменной значения. Этот тип представлен единственным значением — nil.
2. Boolean (логический). К данному типу относятся значения false (ложь) и true (истина).
При выполнении логических операций значение nil рассматривается как false. Все остальные значения, включая число 0 и пустую строку, рассматриваются как true.
3. Number (числовой). Служит для представления числовых значений.
В числовых константах можно указывать необязательную дробную часть и необязательный десятичный порядок, задаваемый символами «e» или «E». Целочисленные числовые константы можно задавать в шестнадцатеричной системе, используя префикс 0x.
Примеры допустимых числовых констант: 3, 3.0, 3.1415926, 314.16e-2, 0xff.
4. String (строковый). Служит для представления строк.
Строковые значения задаются в виде последовательности символов, заключённой в одинарные или двойные кавычки:
b = ‘это вторая строка’
Строки, заключённые в двойные кавычки, могут интерпретировать C-подобные управляющие последовательности (escape-последовательности), начинающиеся с символа «» (обратный слэш):
(перевод строки),
(возврат каретки);
(горизонтальная табуляция),
Символ в строке также может быть представлен своим кодом с помощью escape-последовательности:
где ddd — последовательность из не более чем трёх цифр.
Кроме кавычек для определения строки могут также использоваться двойные квадратные скобки:
local a = [[Компания «Кронос»]]
Определение строки с помощью двойных квадратных скобок позволяет игнорировать все escape-последовательности, т. е. строка создаётся полностью так, как описана:
local a = [[string
При определении строки с помощью двойных квадратных скобок учитываются символы табуляции и переноса.
Двойные скобки могут быть вложенными. Для того чтобы их не перепутать, между скобками вставляется символ«равно» (=):
local a = [=[определение строки [[string]] в Lua]=]
— будет срока: «определение строки [[string]] в Lua»
5. Function (функция). Функции в Lua могут быть записаны в переменные, переданы как параметры в другие функции ивозвращены как результат выполнения функций.
6. Table (таблица). Таблица представляет собой набор пар «ключ» — «значение», которые называют полями илиэлементами таблицы. Как ключи, так и значения полей таблицы могут иметь любой тип, за исключением nil. Таблицы не имеют фиксированного размера: в любой момент времени в них можно добавить произвольное число элементов.
Подробнее — в статье «Создание таблиц в Lua»
7. Userdata (пользовательские данные). Является особым типом данных. Значения этого типа не могут быть созданы или изменены непосредственно в Lua-скрипте.
Userdata используется для представления новых типов, созданных в вызывающей скрипт программе или в библиотеках, написанных на языке С. Например, библиотеки расширений Lua для «CronosPRO» используют этот тип для представления таких объектов, как:
банки данных (класс Bank);
базы данных (класс Base);
записи (класс Record) и т. п.
8. Thread (поток). Соответствует потоку выполнения. Эти потоки никаким образом не связаны с операционной системой и поддерживаются исключительно средствами самого Lua.
Как в Lua задать тип переменной?
Lua не предусматривает явного задания типа переменной. Тип переменной устанавливается в момент присвоения переменной значения. Любой переменной может быть присвоено значение любого типа (вне зависимости от того, значение какого типа она содержала ранее).
a = 123 — переменная a имеет тип number
a = «123» — теперь переменная a имеет тип string
a = true — теперь переменная a имеет тип boolean
a = <> — теперь переменная a имеет тип table
Переменные типа table, function, thread и userdata не содержат самих данных, а хранят ссылки на соответствующие объекты. При присваивании, передачи в функцию в качестве аргумента и возвращении из функции в качестве результата копирования объектов не происходит, копируются только ссылки на них.
a = <> — создаем таблицу. В переменную a помещается ссылка на таблицу
b = a — переменная b ссылается на ту же таблицу, что и a
a[1] = 10 — элементу таблицы с индексом 1 присвоено значение 10
Остальные данные являются непосредственными значениями.
Как в Lua получить тип переменной?
Тип значения, сохранённого в переменной, можно выяснить при помощи стандартной функции type. Эта функция возвращает строку, содержащую название типа («nil», «number», «string», «boolean», «table», «function», «thread», «userdata»).
t = type («это строка») — t равно «string»
t = type (123) — t равно «number»
t = type (type) — t равно «function»
t = type (true) — t равно «boolean»
t = type (nil) — t равно «nil»
t = type (CroApp.GetBank()) — t равно «userdata»
Как в Lua преобразовать тип переменной?
Lua при необходимости автоматически преобразует числа в строки и наоборот. Например, если строковое значение является операндом в арифметической операции, оно преобразуется в число. Аналогично числовое значение, встретившееся в том месте, где ожидается строковое, будет преобразовано в строку.
a = «10» + 2 — a равно 12
a = «10» + 2 — a равно «10 + 2»
a = "-5.3e-10"*«2» — a равно -1.06e-09
a = «строка» + 2 — Ошибка! Невозможно преобразовать «строка» в число
Значение любого типа можно явным образом преобразовать в строку с помощью стандартной функции tostring.
a = tostring (10) — a равно «10»
a = tostring (true) — a равно «true»
a = tostring (nil) — a равно «nil»
a = tostring (<[1] = «это поле 1»>) — a равно «table: 06DB1058»
Из предыдущего примера видно, что содержимое таблиц функцией tostring не преобразуется. Выполнить такое преобразование можно с помощью функции render.
a = render (10) — a равно «10»
a = render (true) — a равно «true»
a = render (nil) — a равно «nil»
Для явного преобразования значения в число можно использовать стандартную функцию tonumber. Если значение является строкой, которую можно преобразовать в число (или уже является числом), функция возвращает результат преобразования, в противном случае возвращает nil.
a = tonumber («10») — a равно «10»
a = tonumber («10»..".5") — a равно 10.5
a = tonumber (true) — a равно «nil»
a = tonumber (nil) — a равно «nil»
Расстановка комментариев в Lua
Комментарий в Lua начинается двумя знаками «минус» (—) и продолжается до конца строки.
local a = 1 — однострочный комментарий
Если непосредственно после символов «—» идут две открывающие квадратные скобки ([[), комментарий являетсямногострочным и продолжается до двух закрывающих квадратных скобок (]]).
local a = 1 — [[ многострочный
Двойные скобки в комментариях могут быть вложенными. Для того чтобы их не перепутать, между скобками вставляется знак равенства (=):
local a = [[Компания «Кронос»]] — [=[
local a = [[Компания «Кронос»]]
Количество символов «=» определяет вложенность:
local a = [=[определение некоторой строки [[string]] в языке Lua]=] —[==[
local a = [=[определение некоторой строки [[string]] в языке Lua]=]
Операции, применяемые в Lua
В выражениях, написанных на Lua, могут применяться следующие виды операций:
1. Арифметические операции.
Lua поддерживает следующие арифметические операции:
^ (возведение в степень);
% (остаток от деления).
Арифметические операции применимы как к числам, так и к строкам, которые в этом случае преобразуются в числа.
2. Операции сравнения.
В Lua допустимы следующие операции сравнения величин:
= (больше или равно).
Операции сравнения всегда возвращают логическое значение true или false.
Правила преобразования чисел в строки (и наоборот) при сравнениях не работают, т. е. выражение «0» == 0 даёт в результате false.
3. Логические операции.
К логическим операциям относятся:
and (логическое И).
Операция and возвращает свой первый операнд, если он имеет значение false или nil. В противном случае, операция возвращает второй операнд (причём этот операнд может быть произвольного типа).
a = (nil and 5) — a равно nil
a == (false and 5) — a равно false
a == (4 and 5) — a равно 5
or (логическое ИЛИ).
Операция or возвращает первый операнд, если он не false и не nil, иначе он возвращает второй операнд.
a == (4 or 5) — a равно 4
a == (false or 5) — a равно 5
Логические операции and и or могут возвращать значения любых типов.
Логические операции and и or вычисляют значение второго операнда только в том случае, если его нужно вернуть. Если этого не требуется, второй операнд не вычисляется. Например:
a == (4 or f()) — вызова функции f() не произойдет
not (логическое НЕ).
Операция not всегда возвращает true или false.
4. Операция конкатенации.
Для конкатенации (объединения) строк служит операция… (две точки).
a = «Кронос».."-"..«Информ» — переменная a получит значение «Кронос-Информ»
Если один или оба операнда являются числами, выполняется их преобразование в строки.
a = 0..1 — переменная a получит значение «01»
5. Операция получения длины.
В Lua определена операция длины #, которую можно использовать для получения длины строки.
len = #a — len равно 6
len = #«ещё строка» — len равно 10
С помощью операции # можно также узнать максимальный индекс (или размер) массива. Подробнее — в статье «Работа с массивами в Lua» .
Приоритет операций в Lua
В языке Lua выполнение операций осуществляется в соответствии со следующим приоритетом (в порядке убывания):
2. not # — (унарный)
Вызов скриптов из форм
С каждой формой (включая вложенные формы) связан отдельный скрипт, который обычно содержит функции, выполняющие обработку событий формы и её элементов.
Когда форма запускается, её скрипт загружается в глобальное окружение. При возникновении события формы или её элемента система вызывает сопоставленную этому событию функцию-обработчик.
Необходимо отметить, что скрипт формы, хотя и не содержит вызова функции module, фактически является модулем. Это означает, что переменные, объявленные в скрипте формы без ключевого слова local, не выносятся в глобальное окружение и доступны только внутри этого скрипта. Если необходимо сделать какое-либо значение доступным для скриптов других форм, его следует явным образом определить в глобальной таблице _G:
Другой скрипт форм сможет прочитать это значение следующим образом:
Блоки операторов (инструкций)
К основным операторам Lua относятся:
операторы для организации циклов.
Группа операторов может быть объединена в блок (составной оператор) при помощи конструкции do… end.
do — начало блока
end — конец блока
Блок открывает новую область видимости, в которой можно определять локальные переменные.
a = 5 — глобальная переменная a
local a = 20 — внутри do-end определяется локальная переменная а
MsgBox(a) —> 5 (здесь обращение уже к глобальной a)
Оператор присваивания в Lua
Присваивание изменяет значение переменной или поля таблицы. В простейшем виде присваивание может выглядеть так:
a = 1 — переменной a присвоено значение 1
a = b + c — переменной a присвоена сумма значений переменных b и с
a = f(x) — переменной a присвоено значение, возвращённое функцией f(x)
В Lua допускается так называемое множественное присваивание, когда несколько переменных, находящихся слева от оператора присваивания, получают значения нескольких выражений, записанных справа от оператора присваивания:
a, b = 1, 5*c — a равно 1; b равно 5*c
Если переменных больше чем значений, «лишним» переменным присваивается nil.
a, b, c = 1, 2 — a равно 1; b равно 2; c равно nil
Если значений больше чем переменных, «лишние» значения игнорируются.
a, b = 1, 2, 3 — a равно 1; b равно 2; значение 3 не использовано
Множественное присваивание можно использовать для обмена значениями между переменными:
a = 10; b = 20 — a равно 10, b равно 20
a, b = b, a — теперь a равно 20, b равно 10
Условный оператор (if) в Lua
Оператор if проверяет истинность заданного условия. Если условие является истинным, выполняется часть кода, следующая за ключевым словом then (секция then). В противном случае, выполняется код, следующий за ключевым словом else (секция else).
return a — если a больше b, вернуть a
return b — в противном случае — вернуть b
Секция else является необязательной.
Перед каждой итерацией цикла проверяется условие :
если условие ложно, цикл завершается и управление передаётся первому оператору, следующему за оператором while;
если условие истинно, выполняется тело цикла, после чего все действия повторяются.
while i > 0 do — цикл от 10 до 1
Для выхода из цикла до его завершения можно использовать оператор break.
while i > 0 do — ищем в массиве отрицательное значение
MsgBox («Индекс отрицательного значения: »..i)
MsgBox («Массив не содержит отрицательных значений»)
Подробнее об особенностях использования оператора break — в статье «Операторы break и return»
Цикл с постусловием (repeat) в Lua
Оператор repeat предназначен для организации циклов с постусловием и имеет следующий вид:
Тело цикла выполняется до тех пор, пока условие не станет истинным. Проверка условия осуществляется после выполнения тела цикла, поэтому в любом случае тело цикла выполнится хотя бы один раз.
— суммируем значения массива a, пока сумма не превысит 10
MsgBox («Сложено »..i.." элементов. Сумма равна "..sum)
Для выхода из цикла до его завершения можно использовать оператор break.
Подробнее об особенностях использования оператора break — в статье «Операторы break и return»
Циклы с оператором for в Lua
Оператор for предназначен для организации циклов и допускает две формы записи:
простую (числовой for);
расширенную (универсальный for).
Простая форма оператора for
Простая форма оператора for имеет следующий вид:
for var = exp1, exp2, exp3 do
Тело цикла выполняется для каждого значения переменной цикла (счётчика) var в интервале от exp1 до exp2, с шагом exp3.
Шаг может не задаваться. В этом случае он принимается равным 1.
for i = 1, 10 do — цикл от 1 до 10 с шагом 1
MsgBox («i равно »..i)
for i = 10, 1, -1 do — цикл от 10 до 1 с шагом -1
MsgBox («i равно »..i)
Выражения exp1, exp2 и exp3 вычисляются всего один раз, перед началом цикла. Так, в примере ниже, функция f(x) будет вызвана для вычисления верхнего предела цикла только один раз:
for i = 1, f(x) do — цикл от 1 до значения, возвращенного функцией f()
MsgBox («i равно »..i)
Переменная цикла является локальной для оператора цикла и по его окончании не определена.
for i = 1, 10 do — цикл от 1 до значения, возвращенного функцией f()
MsgBox («i равно »..i)
MsgBox («После выхода из цикла i равно »..i) — Неверно! i равно nil
Значение переменной цикла нельзя изменять внутри цикла: последствия такого изменения непредсказуемы.
Для выхода из цикла до его завершения используется оператор break.
for i = 1,#a do — ищем в массиве отрицательное значение
Исправленная версия статьи: Lua за 60 минут Исправленная версия (В процессе перевода на LuaRu) Учебник по Lua для программистов
Содержание
Исправлены [ править ]
- Сообщения переведены на русский язык
- Исправлены ошибки в примерах
Для LuaRu [ править ]
- Переводятся (В РАБОТЕ. ) на LuaRu указания
- И насчёт битовых действий в учебнике LuaRu устаревшие сведения, в версии 5.3 добавлена полноценная их поддержка.
Lua? Что это? [ править ]
Lua — простой встраиваемый язык (его можно встраивать в ваши программы, написанные на иных языках), лёгкий и понятный, с одним видом данных, с однообразным синтаксисом. Совершенный язык для изучения.
Зачем? [ править ]
Lua может вам пригодится:
- если вы игрок (дополнения для World of Warcraft и множества других игр)
- если вы пишете игры (очень часто в играх движок пишут на C/C++, а ИИ — на Lua)
- если вы системный программист (на Lua можно писать дополнения для nmap, wireshark, nginx и других оснасток)
- если вы разработчик-встройщик (Lua очень быстрый, маленький и требует очень мало ресурсов)
Что надо для того, чтобы читать дальше? [ править ]
1. Научитесь программировать. Хотя бы немного. Не важно на каком языке. 2. Установите Lua. Для этого либо скачайте здесь версию 5.3 (http://www.lua.org/download.html), либо ищите ее в репозиториях для linux.
Все примеры из статьи запускайте в терминале командой наподобие «lua file.lua».
Первые впечатления [ править ]
Lua — язык с динамической типизацией (переменные получают виды «на лету», в зависимости от присвоенных значений). Писать на нём можно как в императивном, так и в объектно-ориентированном или функциональном стиле (даже если вы не знаете как это — ничего страшного, продолжайте читать). Вот "Привет, мир!" на Lua:
Что уже можно сказать о языке:
- однострочные комментарии начинаются с двух чёрточек "—"
- скобки и точки-с-запятыми можно не писать
Указания языка [ править ]
Набор условных указаний и повторов довольно обычен:
ПОДУМАЙТЕ: что может означать повтор "для ж = 1, 10, 2 делать . конец"?
В выражениях можно использовать такие вот действия над переменными:
- присваивание: x = 0
- счётные: +, -, *, /, % (остаток от деления), ^ (возведение в степень)
- логические: and, or, not
- сравнение: >, =,
= (неравно, да-да, вместо привычного «!=»)
Битовых действий в языке долгое время не было, но в версии 5.2 появилась библиотека bit32, которая их воплощает (как функции, а не как действия).
Виды данных [ править ]
Я вам соврал, когда сказал, что у языка один вид данных. Их у него много (как и у каждого серьёзного языка):
- пусто (nil) (ровным счётом ничто)
- логические значения (да/нет, правда/ложь) (true/false)
- числа (numbers) — без деления на целые/вещественные. Просто числа.
- строки — кстати, они очень похожи на строки в паскале
- функции — да, переменная может быть вида «функция»
- поток (thread)
- произвольные данные (userdata)
- таблица (table)
Если с первыми видами все понятно, то что же такое userdata? Вспомним о том, что Lua — язык встраиваемый, и обычно тесно работает с частями программ, написанными на других языках. Так вот, эти «чужие» части могут создавать данные под свои нужды и хранить эти данные вместе с lua-объектами. Отсюда userdata — и есть "подводная часть айсберга", которая с точки зрения языка lua не нужна, хотя не обращать внимания на неё мы не можем.
А теперь самое важное в языке — таблицы.
Таблицы [ править ]
Я вам снова соврал, когда сказал, что у языка 8 видов данных. Можете считать, что он один: всё — это таблицы (это, кстати, тоже неправда). Таблица — это очень изящный строй данных, он сочетает в себе свойства ряда, хэш-таблицы («ключ»-«значение»), структуры, объекта.
ПОДУМАЙТЕ: чему равно ж[2] в случае разреженного ряда?
В примере выше таблица ведёт себя как ряд, но на самом деле — у нас ведь есть ключи (номера) и значения (элементы ряда). И при этом ключами могут быть какие угодно виды, не только числа:
Кстати, раз уж у таблицы есть ключи и значения, то можно в повторе перебрать все ключи и соответствующие им значения:
А как же объекты? О них мы узнаем чуть позже, вначале — о функциях.
Функции [ править ]
Вот пример обычной функции.
Функции языка позволяют принимать несколько доводов, и возвращать несколько ответов. Так доводы, значения которых не указаны явно, считаются равными пусто (nil).
ПОДУМАЙТЕ: зачем может понадобиться возвращать несколько ответов?
Функции могут принимать переменное количество доводов:
Поскольку функции — это полноценный вид данных, то можно создавать переменные-функции, а можно передавать функции как доводы других функций
Объекты = таблицы + функции [ править ]
Раз мы можем сохранять функции в переменных, то и в полях таблиц тоже сможем. А это уже получаются как-бы-методы. Для тех, кто не знаком с ООП скажу, что основная его польза (по крайней мере в Lua) в том, что функции и данные, с которыми они работают находятся рядом — в пределах одного объекта. Для тех, кто знаком с ООП скажу, что классов здесь нет, а наследование прототипное.
Перейдем к примерам. Есть у нас объект, скажем, светильник. Он умеет гореть и не гореть. Ну а действия с ним можно проделать два — включить и выключить:
А если светильник сделать объектом, и функции выключить и включить сделать полями объекта, то получится:
Мы вынуждены передавать сам объект светильника в качестве первого довода, потому что иначе наша функция не узнает с каким именно светильником надо работать, чтобы сменить состояние вкл/выкл. Но чтобы не быть многословными, в Lua есть сокращенная запись, которую обычно и используют — светильник:включить(). Итого, мы уже знаем несколько таких упрощений синтаксиса:
Продолжая говорить о сокращениях, функции можно описывать не только явно, как поля структуры, но и в более удобной форме:
Особые функции [ править ]
Некоторые названия функций таблиц (методов) заняты, и они несут особый смысл:
- __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) — вычисляют результат сравнения ( Наследование [ править ]
Для тех, кто не знает ООП, наследование позволяет расширить функциональность уже существующего объекта. Например, просто светильник умеет включаться-выключаться, а усовершенствованный светильник будет ещё и яркость менять. Зачем нам переписывать методы включить/выключить, если можно их повторно использовать?
В Lua для этого есть понятие мета-таблицы, т.е. таблицы-предка. У каждой таблицы есть одна таблица-предок, и дочерняя таблица умеет делать все, что умеет предок.
- Метатаблица — это обычная таблица, в которой описываются определённые события (например, сложение, вычитание, сравнивание и т.д.)
- В качестве названия события выступает индекс таблицы, а её значение — обработчик события (метод)
setmetatable связывает таблицы новую и таблицу-предок, с помощью метода __index. Этот метод вызывается всякий раз, когда запрашиваемый атрибут таблицы не найдет (в нашем случае — superlamp:turn_on). И поскольку superlamp.__index == nil и lamp.__index == nil, то вызова метода не происходит.
Допустим, что объект-таблицу lamp мы уже создали. Тогда супер-лампочка будет выглядеть так:
Расширение функциональности [ править ]
Родительские таблицы есть у многих видов (ну у строк и таблиц точно, у чисел и булевых чисел, и у пустоты их нет). Допустим, мы хотим складывать все строки с помощью оператора "+", а не "..". Для этого нужно подменить функцию «+» (__add) для родительской таблицы всех строк:
Собственно, мы ещё можем заменить функцию print с помощью «print = myfunction», да и много других приёмчиков можно сделать.
Области видимости [ править ]
Переменные бывают глобальные и местные. При создании все переменные в Lua являются глобальными.
Для указания местной области видимости пишут ключевое слово local:
Не забывайте об этом слове.
Обработка ошибок [ править ]
Часто, если возникают ошибки, надо прекратить выполнение определённой функции. Можно, конечно, сделать множество проверок и вызывать «return», если что-то пошло не так. Но это увеличит объём кода. В Lua используется что-то наподобие исключений.
Ошибки порождаются с помощью функции error(x). В качестве довода можно передать всё, что угодно (то, что имеет отношение к ошибке — строковое описание, числовой код, объект, с которым произошла ошибка и т.д.)
Обычно после этой функции вся программа сбойно завершается. А это нужно далеко не всегда. Если вы вызываете функцию, которая может создать ошибку (или её дочерние функции могут создать ошибку), то вызывайте её безопасно, с помощью pcall():
Уставные библиотеки [ править ]
Уставных библиотек мало, зато это позволяет запускать Lua где угодно. Подробнее можно получить их список здесь — http://www.lua.org/manual/5.2/manual.html
Неуставных библиотек много, их можно найти на LuaForge, LuaRocks и в других хранилищах.
Между Lua и не-Lua [ править ]
ВНИМАНИЕ: эту часть советуем читать людям со знанием языка C.
А если нам недостаточно функциональности стандартных библиотек? Если у нас есть наша программа на C, а мы хотим вызывать её функции из Lua? Для этого есть очень простой механизм.
Допустим, мы хотим создать свою функцию, которая возвращает случайное число (в Lua есть math.random(), но мы хотим поучиться). Нам придется написать вот такой код на C:
Т.е. Lua предоставляет нам функции для работы с видами данных, для получения доводов функций и возврата ответов. Функций очень мало, и они довольно простые. Теперь мы собираем нашу библиотеку как динамическую, и можем использовать функцию rand():
А если мы хотим вызывать код, написанный на Lua из наших программ? Тогда наши программы должны создавать виртуальную машину Lua, в которой и будут выполняться Lua-скрипты. Это намного проще:
Вы теперь можете писать на Lua. Если вы узнаете любопытные вещи про Lua, которые можно было бы отразить в статье — пишите!





