Lua for Windows (LfW) – интерпретируемый язык программирования, разработанный подразделением Tecgraf Католического университета Рио-де-Жанейро (Computer Graphics Technology Group of Pontifical Catholic University of Rio de Janeiro in Brazil). Разработанный интерпретатор является свободно распространяемым, с открытыми исходными текстами на языке Си.
По возможностям, идеологии и реализации язык ближе всего к JavaScript, однако Lua отличается более мощными и гораздо более гибкими конструкциями. Хотя Lua не содержит понятия класса и объекта в явном виде, механизмы объектно-ориентированного программирования, включая множественное наследование, легко реализуются с использованием метатаблиц, которые также отвечают за перегрузку операций и т. п.. Реализуемая модель объектно-ориентированного программирования – прототипная (как и в JavaScript).
Язык широко используется для создания тиражируемого программного обеспечения – в частности, на нём написан графический интерфейс пакета Adobe Photoshop Lightroom. Также получил известность как язык программирования уровней и расширений во многих играх (например, World of Warcraft) из-за удобства встраивания, скорости исполнения кода и лёгкости обучения.
Lua обычно называют мультипарадигменным языком. Он обеспечивает небольшой набор базовых механизмов, которые могут быть расширены для решения различных задач, а не набор сложных жёстких спецификаций, обеспечивающих программирование в единой парадигме.
Так, в Lua отсутствует явная поддержка наследования, однако оно легко реализуется с помощью метатаблиц.
За Lua прочно закрепилась слава полуязыка - инструмента, который при случае можно встроить, чтобы заскриптовать приложение, написанное на компилируемом языке вроде С++. Тем не менее Lua является вполне самостоятельным языком, имеющим свой интерпретатор, возможность создания модулей, большое число библиотек, и при этом данный ЯП обладает минимальным размером среди аналогов. Проще говоря у нас есть все, чтобы создавать такие же приложения как на perl, python, и вообще любом другом распространенном языке программирования.
Я могу предложить вам следующие доводы в пользу Lua:
- - приложения будут легко переносимы между Windows и Linux (не факт что код будет работать без изменений, но портирование правда пройдет безболезненно, если не были использованы платформоспецифичные библиотеки)
- - малый оверхед создаваемых программ
- - высокая скорость работы и загрузки приложений
- - возможность оперативно «приклеить» к вашему приложению любую С-библиотеку - лучшего «клея» для библиотек вы не найдете
- - приятный минималистичный синтаксис языка, с возможностью реализации на нем современных парадигм программирования
- - программы на Lua очень легко развертывать
- - малое потребление памяти
Чтобы продемонстрировать возможности Lua, я покажу как с его использованием создать небольшую программу для построения графиков по точкам с возможностью сохранения графика в виде файла изображения.
В качестве графического тулкита будем использовать iup - кроссплатформенную библиотеку, изначально созданную с расчетом использования из Lua.
Установка Lua SDK
В рамках идеи использования Lua как самостоятельного ЯП, была создана сборка Lua for Windows , которая содержит себе библиотеки, необходимые в повседневных задачах, возникающих при программировании под указанную ОС: работы с БД, GUI, парсинг XML и т.д. Пусть вас не смущает, что версия Lua в сборке 5.1, а не 5.2 - особой разницы в нашем случае между ними нет.Скачайте и установите сборку.
Краткое описание концепции iup
Я долго думал, как же расписать процесс создания программы, не вдаваясь подробно в устройство iup. И решил коротко описать его основные принципы:- - iup.dialog является корневым элементом интерфейса программы - в этом контейнере размещаются все элементы
- - позиционирование элементов в контейнере производится при помощи layout-ов: задания правил размещения элемента в контейнере. Iup сам расположит и отрисует элемент согласно правилам. Основные контейнеры - фрейм, вертикальный сайзер, горизонтальный сайзер.
- - обработчики событий задаются в виде функций, прикрепленных к виджету
- - после создания диалога запускается цикл обработки событий
Код программы
Подключение библиотек iup require("iuplua") require("iupluacontrols") require("iuplua_pplot") -- библиотека для работы с Canvas, чтобы сохранять график в файл require("cdlua") require("iupluacd") require("string") -- глобальные переменные для виджетов и настроек программы -- максимальное число графиков plots_number = 5 -- виджеты вкладок, где будут размещаться виджеы ввода данных для каждого графика tabs = {} -- контейнеры для виджетов vboxes = {} -- чекбоксы для выбора того, какие графики строить checkboxes = {} -- здесь храним виджеты с текстом данных о точках coords = {} -- виджеты подписи для каждого графика legends = {} -- виджеты обозначения осей координат global_legend = {} -- к величайшему стыду, в Lua нет стандартной функции split function string:split(sep) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) self:gsub(pattern, function(c) fields[#fields+1] = c end) return fields end -- функция рисует на плоттере график по указаным точкам function draw_plot(pwidget, pnum, data) x = data.value:split(",") y = data.value:split(",") if checkboxes.value == "OFF" then return end if not (#x == #y) or #x == 0 then iup.Message("Ошибка", "Задано неверное число точек для графика " .. pnum) return end iup.PPlotBegin(pwidget, 0) iup.PPlotAdd(pwidget, 0, 0) for i = 1,#x do iup.PPlotAdd(pwidget, x[i], y[i]) end iup.PPlotEnd(pwidget) end -- виджет отвечающий за кнопку построения графика plot_btn = iup.button{ title = "Построить"} -- колбэк для кнопки "построить график" function plot_btn:action() -- создать виджет графопостроителя plot = iup.pplot { expand="YES", TITLE = "Simple Line", MARGINBOTTOM="65", MARGINLEFT="65", AXS_XLABEL = global_legend.value, AXS_YLABEL = global_legend.value, LEGENDSHOW="YES", LEGENDPOS="TOPLEFT", size = "400x300" } -- этот блок для обхода бага - без него подпись к первому графику отображаться не будет iup.PPlotBegin(plot, 0) iup.PPlotAdd(plot,0,0) plot.DS_LEGEND = "" iup.PPlotEnd(plot) -- обходим виджеты с данными for i = 1, plots_number do -- чтобы свеженарисованный графи отобразился с правильной подписью print(legends[i].value) plot.DS_LEGEND = legends[i].value -- рисуем график draw_plot(plot, i, coords[i]) end -- кнопка сохранения графика в картинку на диске save_btn = iup.button{ title = "Сохранить" } -- теперь создаем само окно, где будет отображаться график plot_dg = iup.dialog { iup.vbox -- это вертикальный сайзер, помести в него графопостроитель и кнопку { plot, save_btn }, } -- обработчик кнопки сохранения графика function save_btn:action() -- создаем диалог выбора имени файла ля сохранения -- в связи с ограничениями библиотеки сохранять можно только в EMF fs_dlg = iup.filedlg{DIALOGTYPE = "SAVE", FILTER = "*.emf" } iup.Popup(fs_dlg) -- если файл выбран if tonumber(fs_dlg.STATUS) >= 0 then -- дописать при необходимости нужное расширение pic = fs_dlg.value if not (string.sub(pic, string.len(pic)-3) == ".emf") then pic = pic .. ".emf" end -- создаем псевдо-холст, ассоциированный с файлом tmp_cv = cd.CreateCanvas(cd.EMF, pic .. " 400x300") -- выводим график на холст iup.PPlotPaintTo(plot, tmp_cv) -- сохраняем данные в файл cd.KillCanvas(tmp_cv) end end -- отображаем диалог с графиком plot_dg:showxy(iup.CENTER, iup.CENTER) -- запускаем петлю обработки событий для диалога if (iup.MainLoopLevel()==0) then iup.MainLoop() end end -- в цикле создаем вкладки, в которых мы будем размещать виджеты -- для сбора данных for i=1,plots_number do -- создание текстовых виджетов, куда будут вводиться координаты точек coords[i] = {} for j = 1,2 do coords[i][j] = iup.text { expand="HORIZONTAL", multiline = "YES", VISIBLELINES = 5 } end -- виджет для редактирования подписи к графику legends[i] = iup.text{ expand = "HORIZONTAL" } -- создаем контейнер вкладки и заполняем его элементами vboxes[i] = iup.vbox { iup.hbox { iup.label { title = "Подпись графика:" }, legends[i] }, iup.hbox { iup.label { title="X: ", }, coords[i] }, iup.hbox { iup.label { title="Y: ", }, coords[i] }; expand="YES", } -- меняем заголовк вкладки vboxes[i].tabtitle = "График " .. i -- создаем чекбокс, который будет указывать на то, нужно ли строить -- график по данным из указанной вкладки checkboxes[i] = iup.toggle{ title= "График" .. i, value = "ON" } end -- теперь из заполненных нами контейнеров создаем вкладки tabs = iup.tabs{unpack(vboxes)} -- создаем текстовые виджеты для редактирования подписей осей global_legend = iup.text{} global_legend = iup.text{} -- создаем фрейм для общих настроек графика frame = iup.frame { iup.vbox { iup.label{ title="Использовать данные:", expand="HORIZONTAL" }, iup.vbox { unpack(checkboxes) }, iup.label{}, -- пустую подпись можно использовать как распорку iup.label{title = "Подписи"}, iup.hbox { iup.label{ title = "Ось X "}, global_legend }, iup.hbox { iup.label{ title = "Ось Y "}, global_legend }, iup.label{}, plot_btn }; expand = "VERTICAL", } -- создаем главное окно программы и наносим на него настройки и табы dg = iup.dialog { iup.hbox { frame, tabs }, title="Строим график", size = "HALF" } -- показываем главное окно и запускаем обработку событий dg:showxy(iup.CENTER, iup.CENTER) if (iup.MainLoopLevel()==0) then iup.MainLoop() end
Пара слов о развертывании
Скрипт можно запустить при помощи команды:Lua plotter.exe
В данном случае библиотеки будут подключаться из поддиректории clibs/, которая находится в директории, куда был установлен Lua for Windows. Чтобы максимально компактно упаковать скрипт и библиотеки для переноса на другую машину, достаточно скопировать в одну папку следущие файлы(указаны с относительными путями от директории установки Lua):
Lua.exe lib/lua5.1.dll clibs/cd.dll clibs/cdlua51.dll clibs/iup.dll clibs/iup_pplot.dll clibs/iupcd.dll clibs/iupcontrols.dll clibs/iupgl.dll clibs/iuplua51.dll clibs/iuplua_pplot51.dll clibs/iupluacd51.dll clibs/iupluacontrols51.dll clibs/freetype6.dll
Не забудьте поместить в эту папку и сам скрипт с программой. Теперь вы можете перенести эту папку на другую машину и запустить вашу программы командой, указанной выше. При этом никакие другие действия по установке библиотек и рантайма не нужны.
К сожалению файлы cd.dll, cdluad51.dll и iupcd.dll в данной версии Lua for Windows могут работать некорректно, поэтому рекомендую взять их из архива по ссылке ниже.
Итоги
Архив с рабочей версией , для удобства добавлена пускалка app.bat.Скриншоты:
В результате получили, пусть и неказистую, утилиту, имеющую такой же функционал, как и если бы она была написана на «серьезном» языке программирования. При этом простую в развертывании и суммарным весом менее 2 мб. Потребление памяти - около 7 мб. Исходный код доступен для редактирования, сам Lua интерактивно понятен, что упрощает доработку подобного софта на местах.
На мой взгляд, это отличный выбор для написания учебного софта для школ и институтов, а также для внутреннего использования на предприятиях. Так как слабые машины до сих пор в изобилии присутствуют в подобных местах по всему СНГ, то использование Luа подобным образом целесообразно, особенно в свете постепнного прихода Linux на десктопы. К тому же тенденцию потери исходников самописного софта при жуткой его же забагованности можно приравнять к национальному бедствию.
Теги: Добавить метки
Скрипты на языке 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
… - тело цикла
Перед каждой итерацией цикла проверяется условие
если условие ложно, цикл завершается и управление передаётся первому оператору, следующему за оператором 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»)