Мне действительно нужно иметь целочисленный тип в Lua.
Что я подразумеваю под целым типом - это тип, определяющий обычные операторы (/* + и т.д.) и ведя себя как целое число, внутреннее представление не имеет значения.
Выполнение такой вещи с помощью таблиц очень просто, проблема в том, что я пробовал это, и производительность ужасно бедна (конечно). Вот моя частичная реализация:
function num_op(a, b, calc_func)
local atype = pytype(a)
local btype = pytype(b)
local a_val, b_val
a_val = (atype == "Integer" or atype == "Double") and a[1] or a
b_val = (btype == "Integer" or btype == "Double") and b[1] or b
val = calc_func(a_val, b_val)
if atype == "Integer" and btype == "Integer" then
return Integer:create(val)
else
return Double:create(val)
end
end
numeric_mt = {
__add = function(a, b)
return num_op(a, b, function(a,b) return a + b end)
end,
__sub = function(a, b)
return num_op(a, b, function(a,b) return a - b end)
end,
__div = function(a, b)
return num_op(a, b, function(a,b) return a / b end)
end,
__mul = function(a, b)
return num_op(a, b, function(a,b) return a * b end)
end,
__tostring = function(a)
return tostring(a[1])
end
}
-----------------------------
-- Integer type definition --
-----------------------------
Integer = {}
Integer_mt = table.copy(numeric_mt)
Integer_mt["__index"] = Integer
function Integer:create(value)
local new_inst = {math.floor(value)}
setmetatable(new_inst, Integer_mt)
return new_inst
end
function Integer:className()
return "Integer"
end
Основным штрафным штрафом за то, что я собираю, является (конечно) очень многое распределение. LuaJit умеет оптимизировать работу операторов довольно хорошо, но не выделяет метаданные.
Кто-нибудь думает, что можно будет сделать лучше с пользовательской c-реализацией и userdata? Или это то, чего я преследую невозможным?
NB: я know lua не имеет целых чисел. Я также знаю, что я могу получить те же результаты, используя математику lib. Я хочу получить полную прозрачность при использовании целых чисел, за исключением фазы создания.
EDIT: я собираюсь добавить дополнительную информацию здесь, чтобы все по-прежнему было централизовано
@Mud: Мне нужно, чтобы в определенной степени иметь прозрачную смешанную арифметику так же, как у вас в python/ruby /etc, но с лучшей производительностью. Я использую luaJIT как цель для компилятора, с регулярным Lua как резерв для платформ, не поддерживаемых luaJIT. Это очень важно для характеристик производительности.
Это означает, что я хотел бы иметь возможность сделать это:
a = int(5) -- Integer value
b = int(2) -- Another Integer
c = 2 -- Double
d = a / b -- == 2 , integer arithmetics
e = a / c -- == 2.5, floating point arithmetics
Я могу достичь этого до определенного момента, с реализацией, показанной выше. Проблема в том, что я замедляю операции над каждым числом, так как регулярные числа тоже в коробке. Я мог бы перегрузить metatable чисел с помощью debug lib, но
- Я не знаю, насколько надежна эта функция для использования в программном обеспечении качества продукции.
- Он все равно замедлит работу чисел, поскольку, чтобы иметь унифицированный интерфейс для чисел, мне придется использовать (число): get(), что в любом случае замедлит работу.
Я выполнил свою собственную реализацию Integer в C прошлой ночью. Дело в том, что, хотя это улучшение по сравнению с моей наивной реализацией в регулярных lua, а также улучшение над встроенными вызовами в math.floor, это гораздо менее понятно при использовании LuaJIT, где встроенные вызовы по-прежнему являются лотом быстрее, чем реализация C.
Другим решением было бы всегда использовать unboxed numbers и использовать какой-то тип распространения в моем компиляторе для отслеживания целых чисел и при необходимости использовать соответствующие встроенные операции над ними, но сложность этого решения намного больше и побеждает всю цель использования Lua/LuaJIT в качестве бэкэнд.
Я попытаюсь выполнить вашу реализацию, но я сомневаюсь, что это будет лучше, чем встроенные вызовы в LuaJIT. Вполне возможно, что то, что я снимаю (имея как прозрачную работу двойных, так и целых чисел, а также производительность, близкую к встроенным вызовам luaJIT), просто невозможно. Большое вам спасибо за вашу помощь.
@miky: Спасибо, это выглядит красиво, но я сомневаюсь, что смогу исправить его с помощью luaJIT, и если я не смогу, он потеряет все свои промежутки для моей цели.