Работа со строками, таблицами и файлами
Работа со строками, таблицами и файлами
Что такое строка и как она устроена
Строка — это последовательность символов, используемая для представления текстовых данных. В языке программирования Lua строка является примитивным типом данных, который не изменяется после создания. Это свойство называется неизменяемостью (immutability). Любая операция, которая должна изменить содержимое строки, фактически создает новую строку с измененными данными, оставляя исходную строку без изменений.
Внутреннее представление строки в Lua представляет собой массив байтов. Каждый символ в строке занимает один байт. Для стандартного ASCII-диапазона это соответствует одному символу на один байт. При работе с Unicode-символами (например, кириллицей, эмодзи или иероглифами) ситуация усложняется: один символ может занимать от одного до четырех байт в зависимости от кодировки. Lua по умолчанию использует UTF-8 для строк, что позволяет корректно обрабатывать символы практически всех письменностей мира.
Система управления памятью Lua автоматически отслеживает количество ссылок на каждую созданную строку. Если несколько переменных ссылаются на одну и ту же строковую литерал, система памяти объединяет их в единый объект. Это явление называется интернированием строк (string interning). Интернирование экономит память и ускоряет сравнение строк, так как достаточно проверить равенство указателей на объекты, а не перебирать все символы.
local str1 = "Привет"
local str2 = "Привет"
print(str1 == str2) -- true
-- str1 и str2 указывают на один и тот же объект в памяти
Строки в Lua могут быть заданы двумя способами: с помощью одинарных кавычек '...' или двойных кавычек "...". Оба способа полностью эквивалентны. Разница заключается лишь в удобстве использования при наличии внутри строки соответствующих кавычек. Если строка содержит двойные кавычки, её удобно заключить в одинарные, и наоборот.
Для вставки специальных символов в строку используется механизм экранирования. Символ обратной косой черты \ служит сигналом того, что следующий за ним символ имеет особое значение. Стандартные управляющие последовательности включают:
\n— перевод строки;\r— возврат каретки;\t— горизонтальная табуляция;\\— обратная косая черта;\"— двойная кавычка;\'— одинарная кавычка.
Lua также поддерживает шестнадцатеричное представление символов через последовательность \xHH, где HH — два шестнадцатеричных символа. Это позволяет точно задать любой байт в диапазоне от 0 до 255.
local message = "Строка с переносом\nИ вторая строка."
local tab = "Текст\tс табуляцией"
local quote = "Он сказал: \"Привет\""
local hex = "\x41\x42\x43" -- ABC
Для работы с многострочными текстами, содержащими кавычки и сложные символы, в Lua существует специальный синтаксис с использованием длинных скобок [=[...]]=. Скобки могут иметь разную длину, но открывающая и закрывающая конструкции должны совпадать по количеству квадратных скобок. Внутри такого блока любые символы, включая кавычки и обратные слеши, воспринимаются буквально.
local multiline = [[
Это многострочная строка.
Она содержит кавычки "и '".
Здесь нет необходимости экранировать \ символы.
]]
Длина строки определяется количеством символов в ней. Функция # возвращает длину строки. В случае со строками, содержащими многобайтовые символы, оператор # возвращает количество байт, а не количество символов. Для получения точного количества символов необходимо использовать функции из модуля utf8.
local text = "Привет"
print(#text) -- выведет 6, так как каждый кириллический символ занимает 2 байта
Основные операции над строками
Конкатенация
Конкатенация — это процесс соединения двух или более строк в одну. В Lua для этой цели используется оператор .. (две точки). Оператор соединяет строки слева направо.
local first = "Hello"
local second = "World"
local result = first .. " " .. second
print(result) -- Hello World
При конкатенации участвуют не только строковые типы, но и другие типы данных. Lua автоматически выполняет приведение типов: числа, булевы значения и nil преобразуются в строковое представление. Число превращается в его десятичную запись, булево значение — в строку "true" или "false", а nil — в пустую строку.
local number = 42
local boolean = true
local nilValue = nil
print("Число: " .. number) -- Число: 42
print("Булево: " .. boolean) -- Булево: true
print("Nil: " .. nilValue) -- Nil:
Сравнение строк
Сравнение строк в Lua осуществляется операторами == (равно) и ~= (не равно). Сравнение происходит побайтово. Для латинского алфавита порядок символов соответствует их кодам в таблице ASCII. Для других алфавитов порядок определяется в соответствии с таблицей Unicode.
local a = "abc"
local b = "abd"
print(a < b) -- true, так как 'c' меньше 'd'
print(a == "abc") -- true
print(a ~= "xyz") -- true
Преобразование типов
Функция tostring() преобразует любое значение в строковый формат. Для чисел она возвращает их десятичное представление. Для таблиц, функций и кортежей она возвращает строку вида "table: 0x...", где указатель на адрес памяти.
print(tostring(123)) -- "123"
print(tostring(true)) -- "true"
print(tostring({1, 2})) -- "table: 0x..."
Функция tonumber() выполняет обратное преобразование: строка в число. Если строка не содержит валидного числового представления, функция возвращает nil.
print(tonumber("42")) -- 42
print(tonumber("abc")) -- nil
Поиск подстрок
Функция string.find(s, pattern) ищет первое вхождение шаблона в строке. Она возвращает индекс начала найденной подстроки и индекс её конца. Если подстрока не найдена, функция возвращает nil.
local text = "Lua Programming"
local start, finish = string.find(text, "Programming")
print(start, finish) -- 5 14
Аргумент pattern может быть простой строкой или регулярным выражением. Если передан просто текст, поиск выполняется как точное совпадение.
local text = "Hello World"
print(string.find(text, "World")) -- 7 11
Функция string.sub(s, i, j) извлекает подстроку из строки s, начиная с индекса i и заканчивая индексом j. Индексация начинается с единицы. Если второй индекс опущен, подстрока берется до конца строки. Отрицательные индексы считаются с конца строки.
local text = "Lua"
print(string.sub(text, 1, 2)) -- Lu
print(string.sub(text, -1)) -- a
Методы работы со строками в Lua
Форматирование строк
Функция string.format(fmt, ...) формирует строку на основе формата и списка аргументов. Формат строки начинается со знака % и указывает тип данных и способ вывода.
Основные спецификаторы формата:
%s— строка;%d— целое число;%f— число с плавающей точкой;%x— число в шестнадцатеричном формате;%%— сам знак процента.
local name = "Alice"
local age = 30
local greeting = string.format("Привет, %s! Тебе %d лет.", name, age)
print(greeting) -- Привет, Alice! Тебе 30 лет.
Можно задавать ширину поля и точность вывода. Например, %5d выводит число в поле шириной 5 символов, дополняя пробелами слева. %5.2f выводит число с плавающей точкой с шириной 5 и точностью 2 знака после запятой.
print(string.format("%5d", 42)) -- " 42"
print(string.format("%.2f", 3.14159)) -- "3.14"
Разбиение строк
Функция string.split отсутствует в стандартной библиотеке Lua, поэтому разбиение строк реализуется через циклы и функцию string.gmatch или string.match.
Функция string.gmatch(s, pattern) возвращает итератор, который проходит по всем вхождениям шаблона в строке. Это позволяет легко извлекать слова, разделенные пробелами или другими разделителями.
local text = "один два три"
for word in string.gmatch(text, "%S+") do
print(word)
end
-- Вывод:
-- один
-- два
-- три
Для разбиения строки по конкретному разделителю можно использовать цикл с функцией string.find.
function split(str, sep)
local parts = {}
local start = 1
local sepLen = #sep
while true do
local pos = string.find(str, sep, start, true)
if not pos then break end
table.insert(parts, string.sub(str, start, pos - 1))
start = pos + sepLen
end
table.insert(parts, string.sub(str, start))
return parts
end
local Данные = "apple,banana,cherry"
local fruits = split(Данные, ",")
for _, fruit in ipairs(fruits) do
print(fruit)
end
Замена подстрок
Функция string.gsub(s, pattern, repl) заменяет все вхождения шаблона в строке на указанную замену. Возвращает новую строку и количество выполненных замен.
local text = "cat dog cat"
local new_text, count = string.gsub(text, "cat", "dog")
print(new_text) -- dog dog dog
print(count) -- 2
В качестве замены можно использовать строку, функцию или таблицу. Если передана функция, она вызывается для каждого найденного совпадения с аргументами, равными найденным подстрокам.
local text = "one two three"
local upper_text = string.gsub(text, "%w+", function(word)
return string.upper(word)
end)
print(upper_text) -- ONE TWO THREE
Приведение регистра
Функции string.upper(s) и string.lower(s) преобразуют строку соответственно в верхний и нижний регистр. Эти функции учитывают национальные особенности алфавита.
print(string.upper("hello")) -- HELLO
print(string.lower("HELLO")) -- hello
Удаление пробелов
Функции string.trim, string.ltrim и string.rtrim отсутствуют в стандартной библиотеке Lua. Их реализацию можно выполнить вручную или использовать регулярные выражения.
local text = " hello world "
local trimmed = string.gsub(text, "^%s*(.-)%s*$", "%1")
print(trimmed) -- hello world
Функция string.gsub с паттерном ^%s* удаляет пробелы в начале строки, а (.-)%s*$ — в конце.
Проверка содержимого
Функции string.match(s, pattern) и string.find(s, pattern) позволяют проверять наличие определенных конструкций в строке. string.match возвращает первое найденное совпадение или nil.
local email = "user@example.com"
if string.match(email, "@") then
print("Строка содержит @")
end
Проверка на цифру:
if string.match("123", "^%d+$") then
print("Строка состоит только из цифр")
end
Что такое таблица и как она устроена
Таблица — это универсальная структура данных в Lua, представляющая собой ассоциативный массив. Таблица связывает ключи со значениями. Ключом может служить любой тип данных, кроме nil и NaN. Значением может быть любой тип данных, включая другую таблицу, функцию или ссылку на себя.
Таблица в Lua — это динамическая структура. Её размер меняется автоматически при добавлении или удалении элементов. Нет необходимости заранее выделять память или указывать максимальное количество элементов.
Внутреннее устройство таблицы в Lua оптимизировано для различных случаев использования. Lua использует гибридную структуру хранения: массивная часть для целочисленных ключей и хеш-часть для остальных ключей. Это обеспечивает быстрый доступ к элементам как по числовым, так и по строковым индексам.
local t = {10, 20, 30}
print(t[1]) -- 10
print(t[2]) -- 20
print(t[3]) -- 30
Ключи в таблице могут быть любого типа. Строковые ключи часто используются для создания объектов или структур данных.
local person = {
name = "Ivan",
age = 25,
city = "Moscow"
}
print(person.name) -- Ivan
Таблицы поддерживают рекурсивную структуру. Таблица может содержать другие таблицы, создавая древовидные структуры данных.
local company = {
name = "TechCorp",
departments = {
sales = { head = "Anna" },
it = { head = "Petr" }
}
}
print(company.departments.it.head) -- Petr
Основные операции с таблицами
Создание таблицы
Таблицу можно создать с помощью фигурных скобок {}. Элементы разделяются запятыми. Если элементы имеют имена (ключи), они записываются в виде key = value. Если ключи не указаны, они присваиваются автоматически, начиная с единицы.
local empty_table = {}
local numbers = {1, 2, 3, 4, 5}
local mixed = {name = "Test", value = 100, active = true}
Добавление и удаление элементов
Элементы добавляются в таблицу путем присваивания значения по ключу.
local t = {}
t[1] = "first"
t["second"] = 2
t[3] = {nested = true}
Удаление элемента осуществляется путем присваивания ему значения nil.
t["second"] = nil
Перебор таблицы
Для перебора элементов таблицы используются итераторы. Наиболее распространенный итератор — pairs(). Он проходит по всем парам ключ-значение в произвольном порядке.
local t = {a = 1, b = 2, c = 3}
for key, value in pairs(t) do
print(key, value)
end
Для перебора только числовых ключей, расположенных последовательно, используется итератор ipairs(). Он останавливается при встрече первого nil.
local t = {10, 20, 30, nil, 40}
for index, value in ipairs(t) do
print(index, value)
end
-- Вывод:
-- 1 10
-- 2 20
-- 3 30
-- Цикл завершается, так как элемент 4 равен nil
Изменение размера таблицы
Функция table.insert(t, [pos], value) вставляет элемент в таблицу. Если указан индекс pos, элемент вставляется перед существующим элементом. Если индекс не указан, элемент добавляется в конец.
local t = {1, 2}
table.insert(t, 3)
print(t[3]) -- 3
table.insert(t, 2, 10)
print(t[2]) -- 10
print(t[3]) -- 2
Функция table.remove(t, [pos]) удаляет элемент из таблицы. По умолчанию удаляется последний элемент.
local t = {1, 2, 3}
table.remove(t)
print(t[2]) -- 2
table.remove(t, 1)
print(t[1]) -- 2
Сортировка таблицы
Функция table.sort(t, comp) сортирует элементы таблицы. Аргумент comp — функция сравнения, которая принимает два элемента и возвращает true, если первый должен идти перед вторым.
local numbers = {5, 2, 8, 1, 9}
table.sort(numbers)
print(table.concat(numbers, ", ")) -- 1, 2, 5, 8, 9
Для сортировки таблиц по определенным полям используется пользовательская функция сравнения.
local people = {
{name = "Anna", age = 30},
{name = "Boris", age = 25},
{name = "Cyril", age = 35}
}
table.sort(people, function(a, b)
return a.age < b.age
end)
for _, p in ipairs(people) do
print(p.name, p.age)
end
Объединение таблиц
Функция table.concat(t, sep, i, j) объединяет элементы таблицы в строку, используя разделитель sep. Диапазон элементов указывается параметрами i и j.
local words = {"Hello", "world"}
print(table.concat(words, " ")) -- Hello world
Для объединения двух таблиц можно использовать цикл и оператор присваивания.
local t1 = {1, 2}
local t2 = {3, 4}
for _, v in ipairs(t2) do
table.insert(t1, v)
end
print(table.concat(t1, ", ")) -- 1, 2, 3, 4
Поиск элементов
Функция table.find(t, value) отсутствует в стандартной библиотеке. Поиск выполняется вручную с помощью цикла.
function find(t, value)
for k, v in pairs(t) do
if v == value then
return k
end
end
return nil
end
local t = {a = 10, b = 20}
print(find(t, 20)) -- b
Что такое файл и как он устроен
Файл — это именованный набор данных, хранящийся на носителе информации. В Lua работа с файлами осуществляется через встроенную библиотеку io. Библиотека предоставляет функции для открытия, чтения, записи и закрытия файлов.
Файл в Lua представляется объектом типа file. Объект файла содержит информацию о текущем положении курсора, режиме доступа и пути к файлу. Все операции с файлом выполняются через методы этого объекта или глобальные функции.
Режимы доступа к файлам:
"r"— чтение (файл должен существовать);"w"— запись (файл создается или очищается);"a"— добавление (файл создается или данные дописываются в конец);"r+"— чтение и запись (файл должен существовать);"w+"— чтение и запись (файл создается или очищается);"a+"— чтение и добавление (файл создается или данные дописываются).
local file = io.open("test.txt", "r")
if file then
print(file:read())
file:close()
else
print("Файл не открыт")
end
Открытие файла
Функция io.open(filename, mode) открывает файл и возвращает объект файла или nil в случае ошибки. Второй аргумент mode указывает режим доступа.
local file = io.open("Данные.txt", "w")
if file then
file:write("Привет, мир!")
file:close()
else
print("Ошибка открытия файла")
end
Функция io.input(filename) устанавливает текущий входной файл по умолчанию. Все последующие вызовы io.read() будут читать из этого файла.
io.input("input.txt")
local line = io.read()
Функция io.output(filename) устанавливает текущий выходной файл по умолчанию. Все последующие вызовы io.write() будут писать в этот файл.
io.output("output.txt")
io.write("Текст для записи")
Чтение из файла
Метод file:read([size]) читает данные из файла. Аргумент size определяет формат чтения:
number— прочитатьnбайт;"line"— прочитать одну строку (до перевода строки);"lines"— вернуть итератор для чтения всех строк;nil— прочитать следующую строку.
local file = io.open("text.txt", "r")
if file then
local line = file:read()
print(line)
file:close()
end
Для чтения всего содержимого файла можно использовать итератор.
local file = io.open("text.txt", "r")
if file then
for line in file:lines() do
print(line)
end
file:close()
end
Запись в файл
Метод file:write(...) записывает данные в файл. Аргументы могут быть строками или числами.
local file = io.open("log.txt", "a")
if file then
file:write("Запись №1\n")
file:write("Запись №2\n")
file:close()
end
Позиционирование в файле
Метод file:seek([whence][, offset]) перемещает курсор чтения/записи в файле. Аргумент whence указывает точку отсчета:
"set"— начало файла (по умолчанию);"cur"— текущая позиция;"end"— конец файла.
Аргумент offset — смещение в байтах.
local file = io.open("Данные.bin", "r+b")
if file then
file:seek("set", 0) -- Начало файла
local content = file:read("*all")
file:seek("cur", 10) -- Смещение на 10 байт вперед
local part = file:read(5)
file:seek("end", -5) -- 5 байт от конца
local tail = file:read("*all")
file:close()
end
Закрытие файла
Метод file:close() закрывает файл и освобождает ресурсы. После закрытия файл нельзя использовать для чтения или записи.
local file = io.open("test.txt", "w")
file:write("Текст")
file:close()
Обработка ошибок
Все операции с файлами могут завершиться ошибкой. Рекомендуется проверять результат вызова io.open. Если возвращается nil, следует обработать ошибку.
local file, err = io.open("nonexistent.txt", "r")
if not file then
print("Ошибка:", err)
end
Пример 1: Парсинг CSV-файла
function parse_csv(filename)
local file = io.open(filename, "r")
if not file then
return nil, "Не удалось открыть файл"
end
local rows = {}
for line in file:lines() do
local row = {}
for field in string.gmatch(line, "[^,]+") do
table.insert(row, field)
end
table.insert(rows, row)
end
file:close()
return rows
end
local Данные, error = parse_csv("users.csv")
if Данные then
for _, user in ipairs(Данные) do
print(user[1], user[2])
end
else
print(error)
end
Пример 2: Сохранение и загрузка конфигурации
function save_config(filename, config)
local file = io.open(filename, "w")
if not file then
return false
end
for key, value in pairs(config) do
file:write(key, "=", tostring(value), "\n")
end
file:close()
return true
end
function load_config(filename)
local config = {}
local file = io.open(filename, "r")
if not file then
return nil
end
for line in file:lines() do
local key, value = string.match(line, "(%w+)=(.*)")
if key and value then
config[key] = tonumber(value) or value
end
end
file:close()
return config
end
local settings = {
width = 800,
height = 600,
fullscreen = true
}
save_config("settings.cfg", settings)
local loaded = load_config("settings.cfg")
print(loaded.width, loaded.fullscreen)
Пример 3: Обработка больших файлов
function process_large_file(input_file, output_file)
local input = io.open(input_file, "r")
local output = io.open(output_file, "w")
if not input or not output then
if input then input:close() end
if output then output:close() end
return false
end
for line in input:lines() do
local processed = string.gsub(line, "%s+", " ")
output:write(processed, "\n")
end
input:close()
output:close()
return true
end
process_large_file("input.log", "output.log")
Пример 4: Работа с бинарными файлами
function write_binary(filename, Данные)
local file = io.open(filename, "wb")
if not file then
return false
end
file:write(Данные)
file:close()
return true
end
function read_binary(filename)
local file = io.open(filename, "rb")
if not file then
return nil
end
local Данные = file:read("*all")
file:close()
return Данные
end
local binary_data = string.char(0x00, 0xFF, 0xAA)
write_binary("Данные.bin", binary_data)
local read_data = read_binary("Данные.bin")
print(read_data)
Поддержка UTF-8 в Lua
Lua 5.3 и выше имеет встроенную поддержку UTF-8 через модуль utf8. Модуль предоставляет функции для работы с кодировкой Unicode.
Функция utf8.len(s) возвращает количество символов в строке, учитывая многобайтовую кодировку.
local text = "Привет"
print(utf8.len(text)) -- 6
Функция utf8.codes(s) возвращает итератор, выдающий коды символов в строке.
for code in utf8.codes("A") do
print(code) -- 65
end
Функция utf8.char(...) создает строку из кодов символов.
print(utf8.char(65, 66, 67)) -- ABC
Функция utf8.offset(s, n) возвращает позицию байта, соответствующего n-му символу в строке.
local text = "Привет"
print(utf8.offset(text, 1)) -- 1 (первый символ)
print(utf8.offset(text, 2)) -- 3 (второй символ)
Обработка ошибок кодировки
При чтении файлов с неправильной кодировкой могут возникать ошибки. Рекомендуется явно указывать кодировку при чтении и проверять корректность данных.
local file = io.open("Данные.txt", "r")
if file then
local content = file:read("*all")
-- Проверка на некорректные байты
if string.find(content, "[\128-\191]") then
print("Обнаружены некорректные символы")
end
file:close()
end
Буферизация ввода-вывода
Для повышения производительности при работе с большими объемами данных рекомендуется использовать буферизацию. Функция io.lines() автоматически буферизирует ввод, что ускоряет чтение.
-- Эффективный способ чтения большого файла
for line in io.lines("large_file.txt") do
-- обработка строки
end
Избегание лишних копий строк
При конкатенации множества строк в цикле лучше использовать таблицу и table.concat, чем оператор ...
-- Неэффективно
local result = ""
for i = 1, 1000 do
result = result .. i
end
-- Эффективно
local parts = {}
for i = 1, 1000 do
table.insert(parts, tostring(i))
end
local result = table.concat(parts, "")
Использование потоков вместо файлов
Для временного хранения данных в памяти предпочтительнее использовать таблицы, а не файлы. Файловый ввод-вывод медленнее работы с памятью.
local cache = {}
for i = 1, 10000 do
cache[i] = generate_data(i)
end
-- Дальнейшая работа с таблицей
Паттерн "Фабрика файлов"
Создание абстрактного слоя для работы с файлами позволяет легко менять реализацию.
local FileFactory = {}
function FileFactory.create(filename, mode)
local file, err = io.open(filename, mode)
if not file then
error("Ошибка открытия файла: " .. err)
end
return setmetatable({
_file = file,
_filename = filename,
_mode = mode
}, {
__index = {
read = function(self) return self._file:read() end,
write = function(self, Данные) self._file:write(Данные) end,
close = function(self) self._file:close() end
}
})
end
local f = FileFactory.create("test.txt", "w")
f:write("Тест")
f:close()
Паттерн "Логгер"
Централизованная система логирования с возможностью выбора уровня и формата.
local Logger = {}
function Logger.init(level, file)
local log_file = io.open(file, "a")
Logger.level = level
Logger.file = log_file
end
function Logger.log(level, message)
if level >= Logger.level then
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
Logger.file:write(string.format("[%s] [%s] %s\n", timestamp, level, message))
end
end
Logger.init(1, "app.log")
Logger.log(1, "Информационное сообщение")
Logger.log(2, "Предупреждение")
Паттерн "Кэш конфигурации"
Хранение часто используемых данных в памяти для ускорения доступа.
local ConfigCache = {}
function ConfigCache.load(filename)
if ConfigCache.Данные then
return ConfigCache.Данные
end
local file = io.open(filename, "r")
if not file then
return {}
end
local config = {}
for line in file:lines() do
local key, value = string.match(line, "(%w+)=(.*)")
if key then
config[key] = tonumber(value) or value
end
end
file:close()
ConfigCache.Данные = config
return config
end
local cfg = ConfigCache.load("config.txt")
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Lua — это компактный, быстрый, встраиваемый интерпретируемый язык программирования высокого уровня, разработанный с акцентом на простоту, гибкость и эффективность. Набор советов, правил, принципов и обычаев в разработке на этом языке. LÖVE (Love2D) - 2D-движок для создания игр на Lua, кроссплатформенный, имеет простой API (love.load(), love.update(dt), love.draw()), используется инди-разработчиками и для обучения. Lua 5.1 (2006) — стабильная, самая распространённая версия. Используется в World of Warcraft, Nginx, многих движках. Гайд по установке и настройке с написанием первой программы и её запуском. Кавычки, точки, запятые, скобки и прочие знаки препинания. Lua использует двадцать два зарезервированных ключевых слова. Все они являются частью синтаксиса языка и недоступны для использования в качестве идентификаторов. Набор функций, которые включены в стандартную библиотеку языка. Типизация, набор правил определения типа данных значений языка. Lua предоставляет две формы условной конструкции — if-then-else и её компактный аналог через and/or, хотя последний используется с осторожностью из-за семантических различий. Анонимные функции (или лямбда-выражения) — это функции без имени, которые могут быть определены inline. Они особенно полезны при передаче в качестве аргументов или при создании замыканий. Объектно-ориентированное программирование (ООП) — это парадигма программирования, которая организует код вокруг объектов, объединяющих данные и поведение. В языке Lua отсутствует встроенная поддержка…Основы языка Lua
Рекомендации по разработке на Lua
Экосистема приложений на Lua
История языка Lua
Первая программа на Lua
Синтаксис и пунктуация в Lua
Ключевые слова языка Lua
Встроенные функции и стандартная библиотека Lua
Типы данных и объявление переменных в Lua
Управляющие конструкции и циклы в Lua
Функции, замыкания и анонимные функции
Объектно-ориентированное программирование в Lua