Язык Lua

Драйвера и скрипты в Glial пишутся на языке Lua.

О языке

Lua (лу́а, с порт. — «луна») — скриптовый язык программирования, разработанный в подразделении Tecgraf (Computer Graphics Technology Group) Католического университета Рио-де-Жанейро (Бразилия). Интерпретатор языка является свободно распространяемым, с открытыми исходными текстами на языке Си.

По идеологии и реализации язык Lua ближе всего к JavaScript, в частности, он также реализует прототипную модель ООП, но отличается Паскале-подобным синтаксисом и более мощными и гибкими конструкциями. Характерной особенностью Lua является реализация большого числа программных сущностей минимумом синтаксических средств. Так, все составные пользовательские типы данных (массивы, структуры, множества, очереди, списки) реализуются через механизм таблиц, а механизмы объектно-ориентированного программирования, включая множественное наследование — с использованием метатаблиц, которые также отвечают за перегрузку операций и ряд других возможностей.

Ниже представлены некоторые ссылки, которые помогут вам познакомиться с языком:
Wikipeadia: Lua
Lua за 60 минут
Программирование на языке Lua(книга от автора языка)

Ниже находится краткое введение в язык. Текст основан на этом источнике, все права принадлежат его авторам.

Версия языка, используемая в Glial — 5.1.

Краткий курс Lua

Два дефиса начинают однострочный комментарий:

-- Комментарий

Добавление двух квадратных скобок делает комментарий многострочным:

--[[
    Многострочный
    комментарий
--]]

Можно быстро расскомментировать этот кусок кода добавлением к нему еще одного тире

---[[
    Многострочный
    не комментарий
--]]

Переменные

В основнов, в Lua вам придется пользоваться 6 типами переменных : nil, boolean, number, string, table, function.

num = 42 --Все числа имеют тип double. 
s = 'walternate'  -- Неизменные строки, как в Python.
t = "Двойные кавычки также приветствуются"
u = [[ Двойные квадратные скобки
       начинают и заканчивают
       многострочные значения.]]

Функция type возвращает имя типа любого заданного значения:

print(type("Hello world")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function

Присвоение переменно значениея nil удаляет определение переменной:

t = nil  

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

В Lua есть сборка мусора.

Условия

Блоки обозначаются ключевыми словами, такими как do/end:

while num < 50 do
  num = num + 1  -- Операторов ++ и += нет.
end

Ветвление "если":

if num > 40 then
  print('больше 40')
elseif s ~= 'walternate' then  -- "~=" обозначает "не равно".
  -- Проверка равенства это "==", как в Python; работает для строк.
else
  -- По умолчанию переменные являются глобальными. Как сделать переменную локальной:
  local line = "username"

  -- Для конкатенации строк используется оператор .. :
  print('Зима пришла, ' .. line)
end

Неопределённые переменные возвращают nil. Этот пример не является ошибочным:

foo = anUnknownVariable  -- Теперь foo = nil.

Только значения nil и false являются ложными; 0 и '' являются истинными!

aBoolValue = false

if not aBoolValue then print('это значение ложно') end

Для 'or' и 'and' действует принцип "какой оператор дальше, тот и применяется". Это действует аналогично оператору a?b:c в C/js:

ans = aBoolValue and 'yes' or 'no'  --> 'no'

Циклы

Цикл for:

karlSum = 0
for i = 1, 100 do  -- Здесь указан диапазон, ограниченный с двух сторон.
  karlSum = karlSum + i
end

Используйте "100, 1, -1" как нисходящий диапазон. В основном, диапазон устроен так: начало, конец[, шаг].

fredSum = 0
for j = 100, 1, -1 do fredSum = fredSum + j end

Другая конструкция цикла:

repeat
  print('путь будущего')
  num = num - 1
until num == 0

Функции

function fib(n)
  if n < 2 then return n end
  return fib(n - 2) + fib(n - 1)
end

Вложенные и анонимные функции являются нормой:

function adder(x)
  -- Возращаемая функция создаётся, когда вызывается функция adder,
  -- и запоминает значение переменной x:
  return function (y) return x + y end
end
a1 = adder(9)
a2 = adder(36)
print(a1(16))  --> 25
print(a2(64))  --> 100

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

x, y, z = 1, 2, 3, 4
-- Теперь x = 1, y = 2, z = 3, а 4 просто отбрасывается.

function bar(a, b, c)
  print(a, b, c)
  return 4, 8, 15, 16, 23, 42
end

x, y = bar('zaphod')  --> выводит "zaphod  nil nil"
-- Теперь x = 4, y = 8, а значения 15..42 отбрасываются.


a, b = b, a -- Так можно менять значения переменных местами

Функции могут быть локальными и глобальными. Эти строки делают одно и то же:

function f(x) return x * x end
f = function (x) return x * x end

Эти тоже:

local function g(x) return math.sin(x) end
local g = function(x) return math.sin(x) end

Эквивалентно для local function g(x)..., однако ссылки на g в теле функции не будут работать, как ожидалось:

local g -- 'local g' будет прототипом функции.
g  = function (x) return math.sin(x) end

Вызов функции с одним строковым параметром не требует круглых скобок:

print 'hello'  -- Работает без ошибок.

Вызов функции с одним табличным параметром также не требует круглых скобок (про таблицы в след. части):

print {} -- Тоже сработает.

Таблицы

Таблица — единственная составная структура данных в Lua, представляет собой ассоциативный массив.
Подобно массивам в PHP или объектам в JS, они представляют собой хеш-таблицы, которые также можно использовать в качестве списков.

Использование словарей:

t = {key1 = 'value1', key2 = false} -- Литералы имеют ключ по умолчанию

Строковые ключи используются, как в точечной нотации в JS:

print(t.key1)  -- Печатает 'value1'.
t.newKey = {}  -- Добавляет новую пару ключ/значение.
t.key2 = nil   -- Удаляет key2 из таблицы.

Литеральная нотация для любого значения ключа (кроме nil):

-- 
u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'}
print(u[6.28])  -- пишет "tau"

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

a = u['@!#']  -- Теперь a = 'qbert'.
b = u[{}]     -- Вы могли ожидать 1729, но получится nil:
-- b = nil, т.к. ключ не будет найден.
-- Это произойдёт потому, что за ключ мы использовали не тот же самый объект,
-- который был использован для сохранения оригинального значения.
-- Поэтому строки и числа удобнее использовать в качестве ключей.

Вызов функции с одной таблицей в качестве аргумента не требует круглых скобок:

function h(x) print(x.key1) end
h{key1 = 'Sonmi~451'}  -- Печатает 'Sonmi~451'.

for key, val in pairs(u) do  -- Цикл по таблице.
  print(key, val)
end

Использование таблиц, как списков / массивов:

v = {'value1', 'value2', 1.21, 'gigawatts'} -- Список значений с неявно заданными целочисленными ключами
for i = 1, #v do  -- #v - размер списка v.
  print(v[i])  -- Нумерация начинается с 1!
end

Список не является отдельным типом. "v" - всего лишь таблица с последовательными целочисленными ключами, воспринимаемая как список.

Шаблоны

В Lua есть поддержка регулярных выражений, которые называются шаблонами. Они используются для поиска в функциях string.find, string.gfind, string.match,string.gmatch и string.gsub
%a — латинская буква [A-Za-z]
— контрольные символы
%d — десятичная цифра [0-9] [0123456789]
%u — латинская буква верхнего регистра [A-Z]
%l — латинская буква нижнего регистра [a-z]
%p — знак пунктуации
%s — символ пробела
%w — латинская буква или арабская цифра [A-Za-z0-9]
%z — нулевой символ

%A — не латинская буква [^A-Za-z]
%C — не контрольные символы
%D — не десятичная цифра [^%d] [^0-9]
%U — не латинская буква верхнего регистра [^A-Z]
%L — не латинская буква нижнего регистра [^a-z]
%P — не знак пунктуации
%S — не символ пробела
%W — не латинская буква и не арабская цифра [^A-Za-z0-9]
%Z — не нулевой символ [^%z]

%b — сбалансированная строка: %b() = "(text)", %b%{%} = "{text}"
. — любой символ (точка — %.)

Применение квантификаторов +/-/*/?:
%s — 1 символ пробела
%s+ — 1 или более символов пробела (жадный)
%s- — 0 или более символов пробела (ленивый)
%s* — 0 или более символов пробела (жадный)
%s? — необязательное наличие символа пробела

^ — начало строки, $ — конец строки, () — захват

Символы, которые должны экранироваться %: ( ) . % + - * ? [ ^ $

Захваты

Захват — это способ выделить подстроку из строки, пользуясь шаблонами с помощью string.find. То, что надо поместить в переменную, ограничивается скобочками. Первые два параметра, возвращаемые string.find — начальная и конечная позиция найденных подстрок, следующий — сами подстроки. В данном случае строка, содержащая где-то внутри себя текст "similarity = 60%" будет разбита таким образом, что в переменной similarity окажется числовое значение из одной или нескольких (жадный квантификатор +) цифр (шаблон %d), находящихся между строками "similarity =" (шаблон similarity%s=%s, где %s это символ пробоела) и "%" (шаблон %%, где % — экранирование следующего за ним служебного символа).

local string = "person id = 0 ; similarity = 60% ; cam_id = 1"
local start_pos, end_pos, similarity = string.find(string, "similarity%s=%s(%d+)%%")
print(similarity) -- 60
Last Updated: 7/5/2019, 12:06:02 PM