Пока я писал свою систему для ComputerCraft, мне пришла мысль изобрести велосипед в виде функции require(), которая была удалена из мода по неизвестным мне причинам. Собственно вот код:
function require(...)
local i
local libs = { }
for i=1, #arg do
arg[i] = fs.combine("", arg[i]) --В кавычки можно написать путь к директории с вашими библиотеками.
if not fs.exists(arg[i]) or fs.isDir(arg[i]) then
error("Couldn't find a file by the path #"..i, 2)
end
local g = getfenv()
local t = { }
setmetatable(t, {__index = _G})
t.shell = shell
t.multishell = multishell
setfenv(1, t)
local f=function() dofile(arg[i]) end
local ok, err = pcall(f)
setfenv(1, g)
if not ok then error(err..", in #"..i, 2) end
libs[i] = t
end
return unpack(libs)
end
,,Что-же эта функция делает?"- может кто-то спросить, а тоже что и раньше. Она загружает библиотеку по выбранному вами пути в таблицу (или правильнее будет сказать, в окружение). Самое главное - это то, что вы сможете загружать любое API в любую переменную, в том числе и локальную. Выглядит это примерно так:
local firstVariable, secondVariable = require("APIs/HelloWorld.api", "APIs/Object.lua")
Как вы наверное уже поняли, можно загружать не ограниченное количество библиотек за раз.
Особенности:
загрузка нескольких переменных одновременно;
возможность не захламлять глобальное окружение;
использование библиотек в любой другой таблице;
пропуск shell API и multishell API в окружение вашего API*;
запуск вашего файла с библиотекой во время загрузки (ну это я из пальца выжимаю);
в отличии от стандартной функции, вы не можете использовать require()для поиска библиотеки среди файлов, но по-моему это лишнее в CC, но вы можете указать одну папку (заметка на счёт этого в коде);
вы можете убедится в том, что окружение, куда вы запихнули свою библиотеку, не содержит копию всех функций и переменных из глобального окружения (что хорошо сказывается на производительности).
Для того, чтобы использовать эту функцию, просто вставьте её код в вашу программу. Надеюсь, что это кому-нибудь пригодится.
Дополнение.
Я переделал функцию и добавил взаимодействие с глобальной таблицей package, этот вариант намного лучше предыдущего. Чтобы использовать его скачайте файл с помощью команды:
pastebin get naxXwUey package
Далее загрузите в глобальное окружение с помощью функции dofile("package"). Теперь рассмотрим, что же я изменил.
Во-первых, при повторном вызове функции с одним и тем же API, вы получаете ту же самую таблицу, то-есть:
local var1 = require("lib1")
local var2 = require("lib1")
print(var1 == var2)
-->Вывод: true
Так получается, потому что каждая новая загруженная библиотека сохраняется в таблице package.loaded, а при повторном вызове, вам выдаётся значение из этой таблицы. Я также внес все стандартные API ComputerCraft'а в эту таблицу.
Во-вторых, я добавил значение package.path, оно работает точно также, как и в оригинале. Просто перечисляете директории с библиотеками в током виде:
package.path = "/APIs/?.lua;/Lib/?;/?"
Вы можете изменить это значение в самом файле, я там оставил комментарий.
Также я добавил таблицу package.preload, которая содержит специальные пользовательские функции для загрузки конкретного API, по стандарту я её оставил пустой (что логично). Ключи таких функций являются названиями API, а возвращать они должны функции, которые возвращают само API (правда не знаю, кому это может понадобиться).
И наконец, package.loaders, в этом массиве, расположены функции для загрузки всех API. Их пока две. Аргументом этой функции должно быть имя модуля, а возвращать она должна функцию, загружающую API.
Для тех, кто ничего не понял, просто знайте второй вариант этой функции с дополнением лучше.)))
*Да-да, теперь вам не придётся мучиться и придумывать изощрённые способы получения допуска к функциям этого API в вашей библиотеке!