че как нигер
S81uEc1.png
Гайд | Lua для чайников {2 часть}
-
Универсальный гайд по входу в кодинг на Lua
гайд полностью написан мной (t1m1yep) при помощи своих знаний и документации Lua для octothorp team и его сообщества

обязательно изучи прошлую часть, перед изучением второй!Предисловие
еще раз привет! меня зовут тимофей и во второй части Луа для чайников мы изучим:
- таблицы
- строки (продвинуто)
- замыкания
- конструкторы
- функции (продвинуто)
- библиотеки и require
- работа с ошибками (error handling)
- корутины
- условия (продвинуто)
- и закрепим предыдущий материал!
таблицы
таблица представляет из себя “массив”, который вместо индекса имеет ключ. рассмотрим на примере:
local mytable = {} -- инициализируем пустую таблицу local key = "taiwan" -- создаем переменную-строку "ключ" mytable[key] = "roobys" - задаем значение обьекту таблицы с ключом который мы создали ранее print(mytable[key]) -- выводим значение обьекта таблицы с ключом key!этот код выведет строку “roobys”. давайте немного изменим этот код, в частности, последнюю строку:
local mytable = {} -- инициализируем пустую таблицу local key = "taiwan" -- создаем переменную-строку "ключ" mytable[key] = "roobys" - задаем значение обьекту таблицы с ключом который мы создали ранее print(mytable) -- выводим таблицу без ключа! саму переменнуювыведется что то по типу “table: 0x158e09d80”
что это?!
это адрес таблицы в памяти компьютера. ее местоположение, ячейка, которую она занимает в ОЗУмы можем инициализировать таблицу по другому:
local mytable = {["skumbri"]="скумбри", ["р12"]="r12", ["zverok99"]="зверек99"}в этом случае мы заранее инициализировали обьекты нашей таблицы и ключи к ним. mytable с ключом “skumbri” хранит значение “скумбри”!
также мы можем создать таблицу-матрешку:
local octothorp_team = { managers = {["inquizzy"]="инквиззи", ["vondik"]="вондик"}, admins = {["skumbri"]="скумбри", ["campot"]="кампот"} } print(octothorp_team.managers["inquizzy"]) print(octothorp_team.admins["campot"])только в этом случае нам надо будет обращаться к под-таблицам через точку “.”
примечание: ключи могут быть как и строками, так и числами и даже boolean’ами
примечание: ключи в таблицах указываются в квадратных скобках, а после, через равно идет значениепример итерации по обьектам таблицы:
local octothorp_team = {["doctor"]="доктор",["kilo7"]="кило-семь", ["polkin"]="полкин"} for key, value in pairs(octothorp_team) do print(key, value) endв этом случае я использовал функцию pairs()
этот код выведет:polkin полкин kilo7 кило-семь doctor докторзамыкания
замыкания - “мини функции”
рассмотрим на примере:local myfunction = function (a, b) return a + b end print(myfunction(10, 10))для удобства и чистоты кода - сделаем обьявление функции-замыкания однострочным
local myfunction = function (a, b) return a + b end print(myfunction(10, 10))получается, что мы задаем нашей переменной myfunction значение функции. уже забыл?! функция - это тоже тип данных! я говорил об этом в первой части.
мы можем вызывать эту переменную точно также как и функцию. рассмотрим еще один пример:
function create_closure() return function(a, b) return a + b end end local closure_function = create_closure() print(closure_function(1, 2))closure - замыкание по английски.
мы создаем функцию, которая возвращает функцию-замыкание, а эта функция-замыкания суммирует два числа. получается, что функции точно также могут возвращать функции-замыкания с помощью return. прямо как обычные числа и строки!строки
был бы это си… ой, что-то я замечался, продолжим!
строки имеют свою собственную библиотеку! как бы это банально не звучало, звать ее - string!
рассмотрим функцию gsub библиотеки string. она может заменить часть строки!local a = "доброград плохой сервер" -- создаем строку local b = string.gsub(a, "плохой", "крутой") -- меняем часть строки и записываем в другую переменную print(a) -- неправильная строка print(b) -- правильная строка**выводом будет: **
доброград плохой сервер доброград крутой сервераргументы функции gsub() - первоначальная строка, с которой будут проводится манипуляции; слово которое должно быть изменено; слово НА которое надо изменить
функция gsub() возвращает обновленную строкуоперации с задним слэшем (форматирование текста)
задний слэш - “” в составе строки может иметь после себя определенную букву. каждая строка заканчивается на “\0” - nil символ, он обозначает конец строки. ты его даже не замечаешь! но запомни это, ведь любой инструмент может тебе пригодится (даже старая мышь, вдруг новая сломается!)
\n - знак новой строки. все что будет после него - с новой строки
\t - табуляция
\r - очистить всю консоль! (не ставь это в конце, иначе ничего не увидишь
лучше ставь в начале!)
также имеется большое количество таких операций, их ты можешь найти в интернете.ТВОЙ РОДНОЙ ЯЗЫК ДЖАВАСКРИПТ ЧТО ЛИ С**А?!
наверняка многие из вас видели этот мем

это происходит из за сложения строкlocal яблоко = "яблоко" local одно = "одно" local одно_яблоко = одно + яблокода, баян, но я считаю что стоит осветить эту тему

также мы получим ошибку если попытаемся провести операцию с двумя разными типами:local chelog = "Дмитрий Антонов" local pi = 3.14 local pichelog = chelog + pi -- выдаст ошибку, мы не можем сложить Дмитрия Антонова и 3.14 print(pichelog)
мы можем сложить яблоко с яблоком, но банан с яблоком не можем.
– таинственный кодер
конструкторы
ты до этого применял конструкторы, с таблицами и массивами! да-да, те самые фигурные скобки при создании таблиц и массивов - конструкторы. давай посмотрим пример:
local массив_админов = {"r12", "skumbri", "campot", "timetocoffee", "what"} local таблица_админов = {["рубус"]="roobys", ["эр12"]="r12", ["скумбре"]="skumbri", ["кампот"]="campot", ["кофейня"]="timetocoffee"} print(массив_админов[3]) -- выведет timetocoffee print(таблица_админов["эр12"]) -- выведет r12Библиотеки, require
чтобы создавать чистый и красивый код в больших проектах, скорее всего, тебе придется прибегать к разделению кода по разным категориям
представим такую ситуацию: ты вывел в отдельный файл одну очень сложную функцию (нет) которая возвращает строку “Дмитрий Антонов” и теперь хочешь использовать эту функцию и библиотеку в основном файле. тут тебе поможет require:
файл chelog_library.lua
function dmitry_antonov() return "Дмитрий Антонов" endфайл main.lua
require "chelog_library" local dima = dmitry_antonov() print(dima)почему ты написал только название файла в require? где расширение .lua??
если вы импортируете локальный файл, которого нет папке всех библиотек lua, указывайте только название файла, иначе компьютер будет искать его в корне библиотек и он ее просто не найдет!
также вы можете импортировать из папки:

в таком случае понадобится указать дочернюю папку в main.lua:require "libs/chelog_library" local dima = dmitry_antonov() print(dima)в файле библиотеки ничего менять не нужно.
но что если main.lua тоже находится в папке?

в таком случае нам надо задать package.path перед require:package.path = package.path .. ";../libs/chelog_library.lua" require("chelog_library") local dima = dmitry_antonov() print(dima)
а если библиотека находится вне папки libs, а просто папкой выше main.lua, мы можем убрать из package.path путь в папку “/libs”:package.path = package.path .. ";../chelog_library.lua" require("chelog_library") local dima = dmitry_antonov() print(dima)условия (продвинутые)
рассмотрим несколько условий:
булевы значения в if
local lovechelog = true if lovechelog then print("i love chelog") elseif not lovechelog then print("deleting system...") endвыведется “i love chelog”, а если заменить lovechelog на false, выведется “deleting system…”
ключевое слово “not” буквально обозначает “не”
в случае с булевым значениями не обязательно указывать сравнение по типу: “if boolean == true …”, можно просто написать “if boolean …”, это будет означать одно и тоже. а если надо указать “if boolean == false …”, можно написать “if not boolean”, это означает тоже самое.
elseif входит в состав конструкции if, так как end у них общий. elseif используется только в случае повторения условия с участием одной и той же переменной.
“||” и “&&”
|| - “или”
if 10 > 5 || 20 > 21 then -- выполнится только первая часть условия, но само условие выполнится print("octothorp team") -- надпись выведется endif 10 < 5 || 20 < 21 then -- выполнится только вторая часть условия, но само условие выполнится print("octothorp team") -- надпись выведется end&& - “также”
if 10 > 5 && 20 > 10 then -- условие выполнится print("octothorp team") -- надпись выведется endif 10 > 5 && 20 < 10 then -- условие не выполнится, так как вторая часть не выполнена print("octothorp team") -- надпись НЕ выведется endработа с ошибками
каждый разработчик имеет дело с ошибками и удерживает их (нервно пытается)
error()
функция error() принимает строку, которую будет печатать в консоль
error("ошибка!")выведет:

assert
давайте напишем простенькую программу, которая будет выдавать ошибку если мы будем пытаться прибавить число к строке:
local dima = "dima" local num1 = 10 local numdima = assert(type(num1) == "string", "num1 не должно быть числом") -- assert() вернет false и выключит программу print(numdima) -- мы никогда не узнаем... print(dima, num1) -- мы никогда не узнаем...
поменяем переменную num1 на строку:local dima = "dima" local num1 = "antonov" local numdima = assert(type(num1) == "string", "num1 не должно быть числом") -- assert() вернет true print(numdima) -- выведет true print(dima, num1) -- выведет "dima antonov"
корутины
корутина - асинхронный блок кода (по очереди), мы можем в любой момент остановить ее выполнение, создать другую. они позволяют нам выполнять много кода одновременно, не замедляя выполнение одного другим
создадим корутину:
корутина = coroutine.create(function () print("привет!") -- не выведется, так как горутина запускается в другом потоке! end) print(корутина) -- выведет thread: <адрес потока в котором запускается горутина> print(coroutine.status(co)) -- выведет suspended, корутина приостановлена coroutine.resume(co) -- выведет тот самый "привет!" в консоль, однако пожертвует своей жизнью (я не шучу) print(coroutine.status(co)) -- выведет dead... корутина умерла..немного исправим код и добавим coroutine.yield():
корутина = coroutine.create(function () -- создаем корутину for i=1,3 do -- создаем цикл, он запустится три раза print("корутина с числом", i) -- печатаем номер итерации цикла coroutine.yield() -- функция yield() делает статус suspended, тоесть приостановлена end end) coroutine.resume(корутина) -- теперь мы возобновим коротину. три раза. выведет число 1 print(coroutine.status(корутина)) -- статус suspended, так как после каждой итерации корутина приостанавливает себя и ждет возобновления coroutine.resume(корутина) -- выведет число 2 print(coroutine.status(корутина)) -- suspended! coroutine.resume(корутина) -- выведет число 3 print(coroutine.status(корутина)) -- suspended!если мы попытаемся возобновить коротину через coroutine.resume() которая уже мертва, мы получим ошибку
мы также можем приостанавливать и возобновлять корутину с аргументами:
корутина = coroutine.create(function (a,b) -- коротина-замыкание с двумя аргументами coroutine.yield(a + b, a - b) -- приостанавливаем корутину с аргументами для возобновления end) print(coroutine.resume(корутина, 20, 10)) -- даем те самые аргументы из yield(). выведет 30также коротина может возвращать значения как обычная функция:
корутина = coroutine.create(function () return 6, 7 -- возвращаем числа 6 и 7 end) print(coroutine.resume(корутина)) -- выведет "6 7"Заключение второй части гайда
спасибо что дочитал до этого момента! мне правда приятно что я смогу научить кого-то своим навыкам.
глаза сильно болят и я уже хочу спать, 11 вечера по моему времени я сейчас лопну
(если что, я встал в 6)третяя часть
обратная связь (вопросы насчет кода)
смело пиши мне в личные сообщения дискорда - timofeyw
я постараюсь ответить в кратчайшие сроки
обратная связь (вопросы насчет топика, ошибки топика)
можешь писать прямо в комментарии этого топика или мне в личные сообщения дискорда - timofeyw
спасибо и удачи! третяя часть выйдет как можно скорее
-
@тимиеп Пиздануться можно, но прикольно!
-
-
Т тимиеп делает ссылку на эту тему
