Вывод Lua для классов moonscript - МАССИВНЫЙ
Я хотел бы иметь возможность создавать программы для ComputerCraft с использованием MoonScript, но из-за того, что CC помещается в "песочницу" для предотвращения проблем безопасности на серверах Minecraft и т. Д., Я не могу напрямую запрашивать moonscript и запускать оттуда код moonscript. Я должен преобразовать мой код moonscript в lua.
Однако это проблематично из-за того, что реализация класса для moonscript очень велика и не очень консервативна по размеру файла. Когда я набираю "класс Bacon", он выводит это для lua:
local Bacon
do
local _parent_0 = nil
local _base_0 = { }
_base_0.__index = _base_0
if _parent_0 then
setmetatable(_base_0, _parent_0.__base)
end
local _class_0 = setmetatable({
__init = function(self, ...)
if _parent_0 then
return _parent_0.__init(self, ...)
end
end,
__base = _base_0,
__name = "Bacon",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
if _parent_0 and _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
Bacon = _class_0
return _class_0
end
И это для каждой реализации класса, что довольно смешно. Есть ли способ, которым я могу сократить это в моем коде moonscript?
3 ответа
Объем сгенерированного кода был немного очищен в последней версии 0.2.4: http://leafo.net/posts/moonscript_v024.html
Класс теперь минимально выглядит так
local Hello
do
local _base_0 = { }
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function() end,
__base = _base_0,
__name = "Hello"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Hello = _class_0
end
Просто глядя на код, я могу удалить некоторые мертвые пути из-за _parent_0
быть ноль...
local Bacon
do
local _base_0 = { }
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, ...)
end,
__base = _base_0,
__name = "Bacon",
}, {
__index = function(cls, name)
return rawget(_base_0, name)
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Bacon = _class_0
return _class_0
end
Вы можете найти статический анализатор, чтобы сделать это для вас.
В противном случае, если вас беспокоит только размер кода (в байтах), используйте компрессор (например, Squish).
Вы не можете сократить это в своем коде moonscript. Но вы, возможно, сможете обработать вывод вручную довольно тривиально для рефакторинга общих частей. Стоит ли это делать? Учти это:
- Если вы хотите использовать понятие "класс" в том виде, в каком оно доступно в moonscript, вам все равно придется кодировать все эти шаги (в противном случае вы получите "класс" с другим поведением "класса").
- Разница в том, что в moonscript, N классов приводят к N копиям кода, который вы разместили, отличаясь только двумя строками, в то время как если бы вы реализовали понятие класса в moonscript вручную, вы, вероятно, использовали бы функцию для определения классов, как это делается в некоторых Библиотеки Lua OO: Bacon = newClass("Bacon") будет вызывать вышеуказанный код с заменой строк "__name =" и "Bacon =" соответственно.
- Таким образом, копируя код moonscript вместо кода вручную, каждому классу требуется 20 строк кода (последний moonscript). Но если ваши классы не тривиальны, вполне вероятно, что они будут содержать чуть больше кода, чем 20 строк, возможно, 200.
- Таким образом, хотя вы действительно дублируете 18 строк на класс, это, вероятно, менее 10% кода, который вам придется написать.
- Но это предположение. Если предположение неверно, то возникает вопрос: зачем вам занятия в первую очередь? Просто используйте базовые объекты Lua на основе таблиц с сахаром ':'.
Если вы действительно хотите использовать вывод moonscript, я думаю, что ваш единственный вариант - это сделать рефакторинг вручную. Размещенный вами код может быть помещен в функцию, и нужно изменить только две строки для параметризации имени класса.
Обратите внимание, что есть несколько преимуществ в том, чтобы оставить дублирование кода Lua, сгенерированное moonscript, в ваших файлах Lua, по крайней мере, для часто используемых операций (определение класса, вероятно, не является одним из них, но moonscript делает гораздо больше):
- он сокращает вызовы функций; это, вероятно, увеличит скорость, так как нет необходимости помещать переменные в стек, вызывать функцию, помещать возвращаемые значения в стек, читать стек, извлекать значения из стека). Заметно ли увеличение скорости, во многом будет зависеть от того, как часто вызывается код.
- это удобнее в обслуживании: если все сделано правильно, вы, вероятно, сможете обновить код, когда moonscript будет обновляться легче.