在设计代数方程建模系统时,我遇到了这样的困境:如果我将数字转换为带有字段"值"的数字,我们就无法将属性与数字相关联。例如,我可以重载算术运算符,但不能重载逻辑运算符,因为只有当两个操作数都具有相同的metatable时,才能运行,而我的用户将比较" x"经常使用数字。
例如,这是一个最小方程求解器系统:
x = 0
y = 0
eq1 = {function() return 2*x + 3*y end, rhs = 1 }
eq2 = {function() return 3*x + 2*y end, rhs = 2 }
p = {{x,y},{eq1, eq2}}
solve(p)
" solve()"将处理表" p"得到方程组和rhs的所有系数。但是,重要的是,用户可以将属性与" x"和" y&#34 ;,例如,下限,上限。我尝试使用表格,
x = {val=0, lb=0, ub=3}
y = {val=1,lb=3,ub=5}
....
并为" x"编写元方法和" y"算术运算将作用于x.val和y.val。但是,在脚本环境中,我们还需要比较" x"数字,即"如果x> 0,那么......"。我卡在这里。一个丑陋的解决方案是要求用户在建模方程和脚本时到处使用x.val,y.val。这里有没有人有类似的需要将属性与一个数字相关联,这个数字仍然可以用于算术/逻辑运算?
答案 0 :(得分:2)
这样的事情可行:
x = {val = 10}
mt = {}
mt.__lt = function (op1, op2)
if (type(op1) == 'table') then a = op1.val else a = op1 end
if (type(op2) == 'table') then b = op2.val else b = op2 end
return a < b
end
setmetatable(x, mt)
print(x < 5) -- prints false
print(x < 15) -- prints true
print(x < x) -- prints false
print(5 < x) -- prints true
当然,您可以为其他运算符(__add
,__mul
,__eq
等编写类似的方法。
如果你不想使用type()
/反射,你可以使用一个更脏的技巧,利用一元减号很好,一元的事实:
mt = {}
mt.__unm = function (num) return -(num.val) end
mt.__lt = function (a, b) return -(-a) < -(-b) end
答案 1 :(得分:0)
如果你有权访问调试库,那么这很简单吗?
debug.setmetatable(0, meta)
meta将是所有数字的元数据。这将解决您的逻辑重载问题
但是,如果您希望将属性分配给数字,有一种方法可以做到这一点,我写了一个关于如何做到这一点的快速示例:
local number_props = { {VAL =&#34;喜&#34;}, {VAL =&#34; HI2&#34;} }
debug.setmetatable(0,{__index=function(self,k)return number_props[self][k]end})
print((1).val, (2).val)