Перейти к содержимому
Ktlo

Подобие функции require() в ComputerCraft

Рекомендуемые сообщения

Пока я писал свою систему для 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 в вашей библиотеке!

Изменено пользователем Ktlo

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

os.loadAPI чем не устраивал?Но за прошу лайк, часто когда с ок компа сажусь за кк комп, пишу половину функций неверно. Вот только проблемам есть. Кк не поддерживает полную вставку кода, только 1 строка, а смысл этого велосипеда, если придётся писать os.loadAPI? Хотя, можно её как глобальную функцию в стартап вставить

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

os.loadAPI чем не устраивал?Но за прошу лайк, часто когда с ок компа сажусь за кк комп, пишу половину функций неверно. Вот только проблемам есть. Кк не поддерживает полную вставку кода, только 1 строка, а смысл этого велосипеда, если придётся писать os.loadAPI? Хотя, можно её как глобальную функцию в стартап вставить

Просто, используя эту функцию, можно загружать библиотеки в локальную переменную, не трогая глобальную, а также использовать shell API. Кроме способа, который ты описал, можно использовать функцию dofile("fileName"), если хочешь хранить её в отдельном от программы файле.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ах, да. В ок ее вырезали, поэтому забыл. А если переменная не локальная, то вообще легко - shell.run . Просто в кк особой разницы нет, то ли это глобальная пепеменная, то ли локальная. А вот в ок смысл есть, там память конччится. И, желательно, делай програмки на ок, так как кк, как ни странно , тут нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Код хороший, но подожди ка, а где же таблица и функции package? Это ведь специальный инструмент, что бы не забивать оперативную память, и ускорить работу программы при нескольких одинаковых вызовах require().

Больше об этом написано здесь http://ilovelua.narod.ru/about_lua.html#Module_loaders

Можешь посмотреть как require и package реализовано в ОС https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/resources/assets/opencomputers/loot/OpenOS/lib/package.lua

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Код хороший, но подожди ка, а где же таблица и функции package? Это ведь специальный инструмент, что бы не забивать оперативную память, и ускорить работу программы при нескольких одинаковых вызовах require().

Больше об этом написано здесь http://ilovelua.narod.ru/about_lua.html#Module_loaders

Можешь посмотреть как require и package реализовано в ОС https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/resources/assets/opencomputers/loot/OpenOS/lib/package.lua

Спасибо!Теперь засуну в прогруженные таблицы computer и component

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Имею эмулятор СС, но не имею эмулятора ОС. Может быть можно, написав несколько подобных функций, сэмулировать ОС на эмуляторе СС? Вот require мы уже имеем. Теперь надо создать библиотеки computer, component, event  и т.д и будем иметь полновесный эмулятор ОС.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Имею эмулятор СС, но не имею эмулятора ОС. Может быть можно, написав несколько подобных функций, сэмулировать ОС на эмуляторе СС? Вот require мы уже имеем. Теперь надо создать библиотеки computer, component, event  и т.д и будем иметь полновесный эмулятор ОС.

А зачем эмулировать event? os.pullEvent есть, os.listen сделать просто на параллели и os.pullEvent

Зачем эмулировать компонент? Есть же peripheral.wrap и peripheral.call

А функции computer api выполняет os

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А зачем эмулировать event? os.pullEvent есть, os.listen сделать просто на параллели и os.pullEvent

Зачем эмулировать компонент? Есть же peripheral.wrap и peripheral.call

А функции computer api выполняет os

Затем, чтобы можно было программы, написанные для ОС, отлаживать на эмуляторе СС

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Код хороший, но подожди ка, а где же таблица и функции package? Это ведь специальный инструмент, что бы не забивать оперативную память, и ускорить работу программы при нескольких одинаковых вызовах require().

Больше об этом написано здесь http://ilovelua.narod.ru/about_lua.html#Module_loaders

Можешь посмотреть как require и package реализовано в ОС https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/resources/assets/opencomputers/loot/OpenOS/lib/package.lua

Я изменил код теперь всё должно работать, как было написано в той статье. Спасибо за информацию. Моя программа вышла меньше чем OC. Хотя я её особо не смотрел

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...