Создание встраиваемых сценариев на языке Lua. Lua – скрипты Lua

Lua - язык программирования, создателями которого являются Роберту Иерузалимски, Валдемар Селиш и Луис Энрике ди Фигейреду. С трудом верится, что такой популярный язык могли создать не где-нибудь в Кремниевой Долине или MIT, а в солнечной Бразилии. В стране, которая, казалось бы, находится довольно далеко от центров сосредоточения IT. Тем не менее, в одном из подразделений Католического университета Рио-де-Жанейро смогли создать настолько гибкий и мощный язык, что сейчас он находит широкое применение во многих областях.

Всё началось с разработки вспомогательного языка для нефтяной компании PETROBRAS. Инженерам-нефтяникам требовался графический фронтэнд для обработки данных по симуляции определенных процессов. При этом оборудование могло быть самым разным - и PC DOS, и UNIX, Macintosh, поэтому многие уже существующие языки (Perl, например) просто не подходили, так как работали только на одной из этих систем. На этом этапе был разработан язык под названием DEL (data entry language). Со временем, возможностей этого языка стало не хватать, поэтому был разработан новый язык, названный SOL (simple object language). И, наконец, в 1993 году разработчики поняли, что их можно объединить в один полноценный язык программирования, которые был назван Lua (по-португальски Sol это солнце, а Lua - луна). Кстати, в 1996 году Роберту Иерузалимски и другие авторы языка решили рассказать о своей работе миру и отправили статью про Lua в журнал “Software: Practice & Experience”. Позже про Lua напечатали в журнале “Dr.Dobb’s”, из которого о нем узнал один из главных разработчиков адвенчурных игр в LucasArts. Решив использовать Lua вместо их собственного скриптового языка, он был поражен его простотой и эффективностью. В результате этого большая часть разрабатываемой в тот момент игры была переписана на Lua, что способствовало росту его популярности.

Философия языка Lua

Больше всего идеология Lua схожа с JavaScript. Например, у них обоих прототипная модель для реализации ООП. Однако, Lua гораздо более гибкий и мощный язык. В Lua используются виртуальная машина и сборщик мусора, что делает её более похожей на Java, однако это не мешает ей сохранять свою простоту и элегантность.

В основе языка Lua лежат таблицы, реализуемые при помощи ассоциативных массивов. Таблица здесь означает набор данных, где каждому из уникальных ключей соответствует своё значение.При помощи таблиц в Lua можно представить практически любые данные - обычные массивы, множества, таблицы символов и.т.д. В полях таблицы также могут быть описаны и функции. Проще говоря, если Вы захотите, чтобы в Вашей любимой и игре появился некий персонаж или предмет, то вам достаточно будет знать его имя, чтобы внести в таблицу, функцию, чтобы создать этот объект и ввести координаты игрового мира, в которых он должен появиться.

Стоит упомянуть такжи и о метатаблицах - таблицы, которые позволяют изменять поведение других таблиц. Например, определить, допустимо ли в некоторой ситуации сложение нечисловых значений. Или определить для некоторого события запуск “сборки мусора” (очистки памяти).

Где применяется Lua

Хотя Lua используется и в промышленных приложениях,но самую большую популярность этот язык приобрел в геймдеве. Так как разработчикам бывает трудно вносить изменения в движок игры, а геймдизайнерам постоянно приходится вносить изменения в работу уровней или персонажей, то здесь Lua бывает просто незаменим. На нем очень легко в описать взаимодействие между игроками, запрограммировать NPC (крестьян в скайриме) или поведение боссов при помощи скриптов, которые потом можно быстро изменить, не влияя на движок.

Самой известной игрой, в которой применяется Lua, сейчас, конечно, стала World of Warcraft. Интерфейс WoW (меню, чат и.т.д) написаны на нем. Ещё Lua использовали в таких играх, как Crysis, King’s of Bounty, Warhammer, Аллоды онлайн, CS, Сталкер, Ведьмак, Sim City, Far Cry, Civilization V и.т.д.

Ещё на Lua часто пишутся плагины для nmap, wireshark, nginx или боты для Telegram. А ещё Википедия планирует использовать Lua для встраивания в MediaWiki (можете попробовать в английской версии).

Lua также используется в обсерваториях, занимающихся исследованиями в области астрофизики и крупных университетах по всему миру (например, в Берлинском Техническом Университете). Также Lua стал чем-то вроде национального языка программирования у себя на родине и используется многими местными компаниями и исследовательскими центрами в самых разных сферах деятельности.

Сложность обучения Lua

Lua достаточно прост в изучении. По нему много ресурсов и видеоуроков в сети. К тому же, тут очень помогает геймификация. Если в вашей любимой игре можно создавать моды на Lua, то попробуйте поэкспериментировать с игровым миром в процессе обучения. Это позволит освоить программировании весело и без лишних усилий.

Плюсы/минусы Lua

К плюсам Lua относятся:

  • хорошая портируемость. Если вам потребуется, например, перенести программу из Windows в Linux, то, за исключением некоторых специфичных для платформ библиотек, код не потребуется сильно изменять.
  • возможность быстро добавить к приложению на Lua библиотеку на С
  • легкость развертывания программ
  • легкий синтаксис
  • программы на Lua потребляют мало памяти
  • распространяется по лицензии MIT, поэтому можно бесплатно использовать и для бизнес проектов

Из минусов:

Lua отлично работает настолько, насколько вообще может скриптовый язык. Но чаще всего его применяют совместно с другими языками, хотя он вполне выполнять некоторые задачи самостоятельно. Поэтому, вам нужно будет знать хотя бы ещё один, например,C или С++. Однако, несомненно, знание Lua будет вам большим плюсом при трудоустройстве на должность разработчика игр.

Сопутствующие технологии

LuaJIt - JIT-компилятор для Lua. Используется для задач, в которых критично время выполнения. Работает примерно в шесть раз быстрее стандартного интерпретатора.

Love2D - популярный фреймворк, предназначенный для разработки 2D игр на Lua.

Corona SDK - фреймворк для создания приложений под iOS и Android на Lua. С 2015 года появилась бесплатная версия.

Скрипты на языке 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.

Если локальная переменная определена вне какого-либо блока, её область видимости распространяется до конца скрипта.

local i = 1 - переменная i локальна в пределах скрипта

while i <= a do - цикл от 1 до 5

local a = i^2 - переменная а локальна внутри цикла while

MsgBox(a) --> 1, 4, 9, 16, 25

MsgBox(a) -->

if i > 5 then

local a - переменная а локальна внутри then

MsgBox(a) --> 10

MsgBox(a) --> 5 (здесь обращение к глобальной a)

local a = 20 - переменная а локальна внутри do-end

MsgBox(a) --> 20

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 (строковый). Служит для представления строк.

Строковые значения задаются в виде последовательности символов, заключённой в одинарные или двойные кавычки:

a = «это строка»

b = "это вторая строка"

Строки, заключённые в двойные кавычки, могут интерпретировать C-подобные управляющие последовательности (escape-последовательности), начинающиеся с символа «\» (обратный слэш):

\b (пробел),

\n (перевод строки),

\r (возврат каретки);

\t (горизонтальная табуляция),

\\ (обратный слеш);

\"" (двойная кавычка);

\" (одинарная кавычка).

Обратите внимание

Символ в строке также может быть представлен своим кодом с помощью escape-последовательности:

где ddd - последовательность из не более чем трёх цифр.

Кроме кавычек для определения строки могут также использоваться двойные квадратные скобки:

Определение строки с помощью двойных квадратных скобок позволяет игнорировать все escape-последовательности, т. е. строка создаётся полностью так, как описана:

local a = [] в Lua]=]

Будет срока: «определение строки [] в 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 = 10 - элементу таблицы с индексом 1 присвоено значение 10

MsgBox(b) --> "10"

MsgBox(a) --> "20"

Остальные данные являются непосредственными значениями.

MsgBox(a) --> "20"

MsgBox(b) --> "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»}) - a равно «table: 06DB1058»

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

a = render (10) - a равно «10»

a = render (true) - a равно «true»

a = render (nil) - a равно «nil»

a = render ({ = «это поле 1»}) - a равно "{ = «это поле 1»}"

Для явного преобразования значения в число можно использовать стандартную функцию 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 = [=[определение некоторой строки [] в языке Lua]=] --[==[

local a = [=[определение некоторой строки [] в языке 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 определена операция длины #, которую можно использовать для получения длины строки.

a = «строка»

len = #a - len равно 6

len = #«ещё строка» - len равно 10

Обратите внимание

С помощью операции # можно также узнать максимальный индекс (или размер) массива. Подробнее - в статье «Работа с массивами в Lua» .

Приоритет операций в Lua

В языке Lua выполнение операций осуществляется в соответствии со следующим приоритетом (в порядке убывания):

2. not # - (унарный)

6. < > <= >= ~= ==

Вызов скриптов из форм

С каждой формой (включая вложенные формы) связан отдельный скрипт, который обычно содержит функции, выполняющие обработку событий формы и её элементов.

Когда форма запускается, её скрипт загружается в глобальное окружение. При возникновении события формы или её элемента система вызывает сопоставленную этому событию функцию-обработчик.

Необходимо отметить, что скрипт формы, хотя и не содержит вызова функции module, фактически является модулем. Это означает, что переменные, объявленные в скрипте формы без ключевого слова local, не выносятся в глобальное окружение и доступны только внутри этого скрипта. Если необходимо сделать какое-либо значение доступным для скриптов других форм, его следует явным образом определить в глобальной таблице _G:

local a = _G.var

Блоки операторов (инструкций)

К основным операторам Lua относятся:

присваивание;

условный оператор;

операторы для организации циклов.

Группа операторов может быть объединена в блок (составной оператор) при помощи конструкции do… end.

do - начало блока

<оператор1> - тело блока

<оператор2>

<операторN>

end - конец блока

Блок открывает новую область видимости, в которой можно определять локальные переменные.

a = 5 - глобальная переменная a

local a = 20 - внутри do-end определяется локальная переменная а

MsgBox(a) --> 20

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).

if a > b then

return a - если a больше b, вернуть a

return b - в противном случае - вернуть b

Секция else является необязательной.

if a < 0 then

a = 0 - если a меньше 0, присвоить a значение 0

Вместо вложенных операторов if можно использовать конструкцию elseif. Например, приведенный код:

будет проще для восприятия, если заменить его следующим:

return «Иван» - если a равно 1

elseif a == 2 then

return «Петр» - если a равно 2

elseif a == 3 then

return «Сергей» - если a равно 3

return «Нет такого игрока» - если a - ни одно из перечисленных

Цикл с предусловием (while) в Lua

Оператор while предназначен для организации циклов с предусловием и имеет следующий вид:

while do

… - тело цикла

Перед каждой итерацией цикла проверяется условие :

если условие ложно, цикл завершается и управление передаётся первому оператору, следующему за оператором while;

если условие истинно, выполняется тело цикла, после чего все действия повторяются.

while i > 0 do - цикл от 10 до 1

t[i] = «поле »..i

a = {3, 5, 8, -6, 5}

while i > 0 do - ищем в массиве отрицательное значение

if a[i] < 0 then break end - если найдено, прерываем цикл

i = i - 1 - иначе переходим к следующему элементу

if i > 0 then

MsgBox («Индекс отрицательного значения: »..i)

MsgBox («Массив не содержит отрицательных значений»)

Примечание

Цикл с постусловием (repeat) в Lua

Оператор repeat предназначен для организации циклов с постусловием и имеет следующий вид:

… - тело цикла

until

Тело цикла выполняется до тех пор, пока условие не станет истинным. Проверка условия осуществляется после выполнения тела цикла, поэтому в любом случае тело цикла выполнится хотя бы один раз.

Суммируем значения массива a, пока сумма не превысит 10

a = {3, 2, 5, 7, 9}

sum = sum + a[i]

until sum > 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.

a = {3, 5, 8, -6, 5}

for i = 1,#a do - ищем в массиве отрицательное значение

if a[i] < 0 then - если найдено...

index = i - сохраняем индекс найденного значения...

break - и прерываем цикл

MsgBox («Индекс отрицательного значения: »..index)

Примечание

Подробнее об особенностях использования оператора break - в статье «Операторы break и return»)

LUÁ, iau, vb. I. tranz. I. 1. A prinde un obiect în mână spre a l ţine (şi a se servi de el) sau spre a l pune în altă parte. ♢ expr. A lua altă vorbă = a schimba (cu dibăcie) subiectul unei discuţii. A(şi) lua picioarele la spinare = a pleca… … Dicționar Român

Lua - Logo Basisdaten Paradigmen: Skriptsprache, imperativ, funktional, objektorientiert … Deutsch Wikipedia

Lua - [] Información general Paradigma Multiparadigma: interpretado, imperativo, funcional, orientado a objetos, basado en prototipos Apareció en … Wikipedia Español

LUA - Apparu en 1993 Auteur Luiz Henrique de Figueiredo, Roberto Ierusalimschy et Waldemar Celes Implémentations Lua, LuaJIT, LLVM Lua, LuaCLR, Nua, Lua A … Wikipédia en Français

LUA - (portugiesisch für Mond) ist eine Skriptsprache zum Einbinden in Programme, um diese leichter weiterentwickeln und warten zu können. Eine der besonderen Eigenschaften von Lua ist die geringe Größe des kompilierten Skript Interpreters. Lua wurde… … Deutsch Wikipedia

lua - s. f. 1. O único planeta satélite da Terra. 2. Tempo compreendido entre dois novilúnios. 3. Mês. 4. Cio. 5. O mesmo que peixe lua. 6. Disco de ouro ou prata que os Timores usam ao pescoço, como símbolo de… … Dicionário da Língua Portuguesa

Lua - may refer to: * Lua (programming language), a lightweight, extensible programming language * Lua (Yu Gi Oh! 5D s) * Lua (goddess), the Roman goddess * Lua (martial art), a traditional Hawaiian martial art * Lua (song), a single by the folk rock… … Wikipedia

LUA аббревиатура: LUA последний всеобщий предок (также переводится как «Последний универсальный предок» (англ. LUA, Last Universal Ancestor), иначе Последний универсальный общий предок (англ. LUCA, last universal common… … Википедия

lúa - (Del gót. lôfa, palma de la mano). 1. f. Especie de guante hecho de esparto y sin separaciones para los dedos, que sirve para limpiar las caballerías. 2. Mar. Revés de las velas por la parte donde van cazadas con viento largo o en popa. 3. Mar.… … Diccionario de la lengua española

Lua - Lua, römische Göttin, Tochter des Saturnus, welcher nach der Schlacht zur Sühne des vergossenen Blutes erbeutete Waffen von dem Feldherrn verbrannt wurden … Pierer"s Universal-Lexikon

LUA - Dea quaedam apud vett, a luendo, expiandoque nomen sortita, quae praeerat lustrationibus, et lustris. Vide Turneb. Adver s. l. 16. c. 20. et l. 23. c. 23. et l. 19. c. 11. Eius meminit A. Gell. l. 13. c. 22. cum ait in libris Sacerdotum Pop. Rom … Hofmann J. Lexicon universale

Книги

  • Программирование на языке Lua , Иерузалимски Роберту. Книга посвящена одному из самых популярных встраиваемых языков - Lua. Этот язык использовался во многих играх и большом количестве различных приложений. Язык сочетает небольшой объем…
  • Программирование на языке Lua. 3-е издание , Иерузалимски Р.. Книга посвящена одному из самых популярных встраиваемых языков - Lua. Этот язык использовался во многих играх и большом количестве различных приложений. Язык сочетает небольшой объем…

Lua (от португальского «луна») - интерпретируемый язык программирования, разработанный Computer Graphics Technology Group of Pontifical Catholic University of Rio de Janeiro in Brazil. является свободно распространяемым, с открытыми исходными текстами на языке Си. По своим возможностям и реализации он ближе всего к JavaScript, но , с моей точки зрения, более гибок и имеет более широкие возможности. Несмотря на то, что Lua не имеет таких понятий, как “класс” или “объект”, на его базе вполне возможно построение ООП-программ на базе метатаблиц, которые также позволяют реализовать, например, перегрузку операций.

В этом уроке я хочу дать вам немного самых общих сведений об этом языке, а в следующих уроках покажу вам на практике как можно применять язык Lua для решения задач программирования игр.

История Lua

Как я сказал выше, Луа был разработан одним из подразделений Католического университета Рио-де-Жанейро. Произошло это аж в далёком 1993 году. Но с того момента активно развивался и периодически выходили новые версии Lua – он становился удобнее, быстрее, функциональнее. В данный момент стабильной версией Lua является 5.1, однако уже доступна alpha-версия 5.2.

Типы Lua

В Lua насчитывается восемь основных типов данных:

  • nil (неопределенный)
  • boolean (логический)
  • number (числовой)
  • string (строковый)
  • function (функция)
  • userdata (пользовательские данные)
  • thread (поток)
  • table (таблица)

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

Таблицы Lua

Таблицы являются наиболее важным типом данных в Lua – именно таблицы являются основой для хранения и использования пользовательских типов данных: структуры, массивы, списки, множества и т.д. реализуются в Lua именно через таблицы. Таблица в Луа представляет собой набор пар [Ключ, Значение], где в качестве ключа может быть значение любого типа, кроме nil.

Устройство Lua

Как и многие интерпретируемые языки программирования, реализация Lua имеет отдельный компилятор исходного в исполняемый байт-код и виртуальную машину для исполнения сгенерированного байт-кода. В случае Lua байт-код представляет из себя не машинные команды, а команды “виртуального процессора Lua” с несколькими регистрами, что повышает эффективность исполнения. В виртуальной машине Lua используется так же и принцип сборки мусора (аналогично Java или.NET), который позволяет программисту не заботиться о выделении/удалении памяти – этим занимается сам интерпретатор.

Для критичных задач, имеется компилятор Lua: , который позволяет получить более быстрый код.

Где используется Lua

Lua, за долгие годы его существования и развития, завоевал сердца многих разработчиков ПО и в наше время он используется в самых разнообразных областях программирования: в скриптинге компьютерных игр (Crysis, Far Cry, Diablo 3, S.T.A.L.K.E.R.), на серверах MMO-игр (World of Warcraft, Аллоды Онлайн), в пакетах графики (например, в Adobe Photoshop Lightroom), в игровых движках и конструкторах игр (INSTEAD), для программирования GUI некоторых приложений (тот же самый Photoshop Lightroom) и во многих других задачах.

Документация по Lua

Вообще, документации, как и примеров использования, в сети достаточно много. Потому я не буду особо углубляться в эту тему. Скажу лишь, что могу посоветовать вам почитать

Как это будет выглядеть? Конечно не в виде справки, лишь при изучении какой-то сложной функции будет цитироваться русскоязычная справка по луа с сайта Lua.ru, материал я постараюсь преподнести в форме задача — ее решение, начиная с простого и продвигаясь дальше. Не думаю что за платформу для изучения стоит брать какой-либо хаб, так что мы будем использовать пакет LuaAIO (all in one), с помощью которого мы будем проверять код на луа. Скачать пакет можно , там же лежит справка по пакету, она полностью на английском языке и как-то странно собрана что просто не работает, рабочую версию подготовил alex82 , за что ему огромное спасибо, вот . В этой справке есть мануал по луа, первая редакция книги Programming in Lua в электронном виде и справка по библиотекам, включенным в набор LuaAIO.

Итак, скачали, распаковали, теперь запускаем файл lua.exe, открылось окно редактора, написанного на луа с применением библиотек из пакета луааио, в это углубляться не будем, скажу лишь что файл что мы запустили — среда исполнения кода, сам код находится в файле с таким же именем, но с расширением.lua, в нашем случае это lua.lua.

Начем конечно же с банального примера вывода в консоль «Hello world!», на луа это весьма простой код:

print ("Hello world!" )

Теперь разберемся с тем как посмотреть результат работы скрипта, для начала нам надо его сохранить, для этого выбираем File -> Save или нажимаем Ctrl+S, выбираем имя файла, указывать можно любое, к примеру, example1.lua. Следующим шагом будет запуск нашей программы, тот редактор в котором мы работаем позволяет делать это прямо в нем, так что выбираем в верхнем меню Debug -> Run или нажимаем просто F5, видим появившееся внизу окно, в котором отобразился следующий текст:

> Program example1.lua is running
Hello world!

Вот он, результат работы! Теперь останавливаем скрипт выбрав Debug -> Stop или нажав F6, к тексту дописалось

> Program example1.lua is stopped

что означает что скрипт остановлен (теперь можно свернуть до самого низа это окно, оно вылезет само при следующем запуске). А вот сейчас уже разберем сам скрипт на запчасти, узнав что в нем означает каждый символ. Сразу скажу что углубляться в фишки и разнообразные уловки написания скриптов я не буду, поэтому код идет в стандартном (в моем понимании) виде и содержит обычне конструкции. И еще одно небольшое отступление, если вы не владеете логикой, не можете составить план работы и продумать исполнение самого скрипта, то лучше и не браться, а уж если взялись — стараться разобраться самому что да как, а не доставать не очень добрых дядек программистов, они очень сильно начинают нервничать когда пытаются вам на пальцах объяснить что надо сделать и почему именно так, а вы в это время ничего не понимаете или просто «тупите». Если все-таки упрямость играет в вас и вы еще не закрыли этот текст, тогда продолжим. Продолжим с еще одного важного как мне кажется отступления, заключается оно в том, что здешний материал — мое видение, в том числе и русского языка, а не только луа. Любые замечания по этому тексту будут учитываться, но постарайтесь не вступать в спор из-за какой-либо не нравящейся вам запятой или конструкции в коде. Я не мастер луа, но кое-что умею, об этом и постараюсь рассказать.

И снова продолжим (обожаю такие отступления, они заставляют и тебя и собесеников держать нить разговора))), начнем с того как выглядит вызов функции в луа. Функция — некий набор инструкций, выполняющийся по вызову. В функцию так же могут передаваться аргументы (параметры), хотя это и не обязательно, переданные аргумент можно использовать исключительно внутри функции (об областях видимости переменных расскажу позднее). Допустим, что у нас есть некая функция SomeFunction, вот пример ее вызова без аргуменов:

SomeFunction()

и с аргументами one и two, они разделяются запятыми:

SomeFunction(one, two)

Теперь о нашем коде, надеюсь теперь видно что у нас имеется вызов функции print, имеющей один аргумент, которым является «Hello world!». Функция print — стандартная (базовая) функция, предоставленная луа, она выводит данные в стандартное окно вывода, эта функция может принимать любое число аргументов любого типа, выводя их друг за другом в преобразованном в строку виде.

А сейчас настало время поговорить о типах переменных, это один из значимых моментов в программирвании на луа. В этом языке существуют следующие типы данных (этот и некоторый далее материал заимствован с сайта ilovelua.narod.ru):

nil — ничего, обозначает отсутствие какого либо значения
boolean — булевская переменная, принимает значения true либо false
number — числовой тип
string — строковый тип
function — функция
userdata — специальный тип данных, позволяющий хранить в Lua данные из С (фактически это указатель void*)
thread — сопрограмма Lua (позволяет организовать превдо-многопоточность)
table — таблица — ассоциативный массив (набор пар ключ-значение), причем в качестве и ключа и значения может выступать любой тип данных

Lua — язык с динамической типизацией, то есть тип переменной устанавливается не заранее, как, например, в С, а в момент присвоения переменной значения. Примеры:

var = true — var — переменная типа boolean
var = 1 — теперь var число
var = "string" — теперь var строка
var = function (a, b) return a + b end — а теперь var функция, которая принимает два параметра и возвращает их сумму
var = coroutine.create (var) — а теперь var сопрограмма
var = { } — а тепеь var таблица
var = nil — а теперь… теперь var отсутствует, перменаая уничтожена

Два символа — означают начало однострочного комментария, в котором может записываться что угодно.

А теперь после этой маленькой справки ответьте мне к какому типу относится «Hello world!»? Правильно, это строка, если вы думаете иначе — читаем все заново. Вот и весь разбор полетов, вышло что в нашем простом скрипте имеется один вызов стандартной функции луа что выводит в консоль любые переданные ей параметры, преобразовывая их в строку, мы передаем фукнции один аргумент, являющийся строкой «Hello world!», которую мы и видим в консоли после запуска скрипта.

Мой вам совет: если не понятен смысл речевых конструкций лучше не пропускать этот момент и постараться понять что написано в этой простенькой справке, иначе можно упустить важные моменты и в самом простом моменте в скрипте сесть в лужу.

Немного порадовавшись переходим к как мне кажется важной справке, следует принять её как должное. В луа мы можем объявлять переменные, которые могут являться любым из типов луа, но так же есть зарезервированные имена переменных, ими пользоваться нельзя, это приведет к нарушению работы вашего скрипта! Вот полное перечисление:

and break do else elseif
end false for function if
in local nil not or
repeat return then true until while

Так называть переменные нельзя т.к. эти слова используются в конструкциях языка луа. Давайте договоримся дальше что писать названия переменных мы будем в соответствии с венгерской нотацией, то есть называть переменные в соответствии с их типом, начиная переменную с маленькой буквы, обозначающей тип переменной, а уже дальше писать само имя нашей переменной:

s — string
i — integer
b — boolean
h — handle
t — table
mt — metatable

Примеры: sData, iShareSize, bConnected, hFile, tTable, mtTable. Примечанице: здесь под handle подразумевается тип userdata.

Теперь справка по спец. символам в строках луа, вот цитата из лексических соглашений:

Литеральные строки должны быть заключены в одинарные или двойные кавычки и могут содержать следующие С-подобные escape-поледовательности: ‘\a’ («звонок»), ‘\b’ («забой»), ‘\f’ («перевод страницы»), ‘\n’ («перевод на новую строку»), ‘\r’ («возврат каретки»), ‘\t’ («горизонтальная табуляция»), ‘\v’ («вертикальная табуляция»), ‘\\\»‘ («двойная кавычка»), and’\» (апостроф [«одинарная кавычка»]). Кроме того, обратный слеш ставится перед концом строки в редакторе, когда для удобства набора длинные непрерывные строки записываются в несколько строк. Символ в строке также может быть представлен своим кодом с помощью escape-последовательности \ddd, где ddd- последовательность из не более чем трех цифр. (Заметим, что если после символа, записанного с помощью своего кода, должна идти цифра, то код символа в escape-последовательности должен содержать ровно три цифры). Строки в Lua могут содержать любые 8-битные значения, включая ноль, который записывается как ‘\0’.

Что реально полезно:

\t — табуляция, применяется для более красивого вывода информации
\\ — так экранируется сам слеш чтобы вывести его как \, в ином случае будет ошибка
\n — перенос строки
\r — возврат каретки
\» — двойная кавычка
\’ — одинарная кавычка

Для переноса строки на разных операционных системах используется разное сочетание символов переноса строки и возврата каретки:

\r\n — windows
\n — *nix
\r — macOS

Пока все, думаю это вам еще надо обдумать, правда на практике все намного понятнее, попробуйте сами сделать выводы через функцию print() и поиграть с типами, кстати, функция type() возвращает тип переданной ей переменной, написав print(type(«»)) мы получим string