Переменные в Lua: объявление через local, экспорт через return и импорт через require
Опубликовано:
В Lua есть особенность: любая переменная по умолчанию создается глобальной. Забытое ключевое слово local может не только замедлить работу программы, но и привести к трудноловимым багам. В этой статье мы разберем, как правильно управлять областью видимости и как превратить обычную таблицу в полноценный изолированный модуль, используя связку return и require.
Lua — язык с динамической типизацией. Это значит, что как и в Python, тип переменных не указывается, он определяется присвоенным им значением и может меняться по ходу выполнения программы.
a = 10 b = "Hello" print(a) print(b) b = 0.75 print(b)
Однако для Lua такой код не считается достаточным. Переменные, объявленные без ключевого слова local, являются глобальными для проекта. В Lua принято избегать глобальных объектов, так как они замедляют работу программы, засоряют память и приводят к скрытым ошибкам из-за случайного перезаписывания данных в разных файлах. Вместо этого для совместного использования сущностей разными файлами проекта создаются локальные таблицы, которые наполняются данными и возвращаются через return. Как это делается программно будет рассмотрено в конце.
Таким образом, чтобы код выше был корректен, имена переменных следует предварять инструкцией local, которая ограничивает область видимости переменной текущим блоком кода. В данном случае — файлом.
local a = 10 local b = 'Hello' local c -- по умолчанию присваивается nil print(a) print(b) b = 0.75 -- изменение значения локальной переменной print(b) c = 1 print(c) d = 3 -- создание глобальной переменной
Что касается функций, то переменные, объявленные выше них, являются для функций внешними локальными (замыканиями). В Lua если в теле функции происходит присвоение имени, которое совпадает с именем внешней переменной, всегда она и имеется в виду, локальная при этом не создается. Это отличается от Python.
local count = 0 local function click() count = count + 1 end click() click() print(count) -- 2
Для того чтобы создать локальную переменную в функции, надо, опять же, использовать инструкцию local.
local function output() local a = io.read() -- если ввести: hello print(a..'!') -- получится: hello! end output()
Если убрать local, то в Lua переменная a утечет в глобальную область видимости даже несмотря на то, что она объявлена внутри функции. Однако это не касается параметров. Lua автоматически делает их локальными.
local function output(text) print(text..'!') end output('hello') -- hello! output(10) -- 10!
Если локальная переменная объявляется внутри условных операторов и циклов, то она живет до ближайшей инструкции end.
local x = 10 -- Видна во всем файле if x > 5 then local x = 20 -- Создали локальную переменную внутри блока IF print(x) -- Выведет: 20 end print(x) -- Выведет: 10
Теперь вернемся к вопросу, как предоставлять доступ к локальным объектам другим файлам проекта, то есть к экспорту локальных имен. Для связи между файлами в Lua используют модули (при этом имеют в виду обычную Lua-таблицу, которая содержит внутри себя функции и переменные). Файл возвращает ссылку на таблицу в памяти через return, а другие файлы могут связать ее с локальной переменной через require.
Файл-экспортер (пример имени export.lua):
local M = {} -- создается пустая таблица M.a = 10 -- добавляемая в нее переменная function M.func(b) -- добавляемая в нее функция print(M.a + b) end return M -- возвращаем таблицу
Файл-импортер:
local m = require("export") -- получаем таблицу print(m.a) -- 10 m.func(115) -- 125
В данном случае файлы не только должны находиться в одном каталоге, но и интерпретация второго должна запускаться из этого каталога (он должен быть текущим).
user@home:~/lua_code/variables$ lua import.lua 10 125
Если файл будет запускаться из каталога на уровень выше, то в requare указывается путь до модуля относительного этого каталога:
local m = require("variables.export") ...
user@home:~/lua_code$ lua variables/import.lua 10 125
Если в первом файле не будет return, то его запрос через require из другого приведет к выполнению кода первого. В файле с таблицей-модулем могут быть свои локальные переменные и функции для внутренних нужд.
Что такое таблицы в Lua будет рассказано в следующих уроках. Здесь же заметим, что выражение подобное M.a = 10 создает не локальную переменную, а поле (ключ) внутри таблицы. Область видимости поля определяется тем, как была объявлена сама таблица. Если она локальна, то ее поля также скрыты от других файлов. При этом инструкция return открывает к ней доступ.