自定义运算符 |
|
Lua 提供了一小组运算符,以及您可以覆盖的更小的一组运算符。 <<
运算符通常用于将对象插入 C++ 中的输出流,但它并不属于其中。 这并不意味着我们不能尝试。 以下代码展示了一种方案,我们可以通过它模拟在 Lua 中定义和使用自定义运算符。
-- Custom operator to evaluate (class) local CustomOp = {} function CustomOp:__div(b) -- eval full operation. return getmetatable(self.a)['__' .. self.op](self.a, b) end setmetatable(CustomOp, {__call = function(class, a, op) -- construct left-half of operation. return setmetatable({a = a, op = op}, CustomOp) end }) function enable_custom_ops(mt) -- enable custom ops on metatable. function mt:__div(op) return CustomOp(self, op) end return mt end -- Output stream (class) ostream = {} ostream.__index = ostream enable_custom_ops(ostream) function ostream:write(s) io.write(s) end ostream['__<<'] = function(self, s) -- '<<' operator self:write(s) return self end setmetatable(ostream, {__call = function(class, file) -- construct output stream file = file or io.output() return setmetatable({file = file}, ostream) end }) cout = ostream() endl = "\n" -- end of line -- example usage local _ = cout /'<<'/ "hello" /'<<'/ endl
--DavidManura,200703
这模仿了类似的 [Python hack]
local sm = setmetatable local function infix(f) local mt = { __sub = function(self, b) return f(self[1], b) end } return sm({}, { __sub = function(a, _) return sm({ a }, mt) end }) end local shl = infix(function(a, b) return a*(2^b) end) print(5 -shl- 4) --> 80
很可爱,对吧? 缺点:每个操作都需要分配一个表。
--MikePall,2007-03-09
local function factorial(n) local y = 1 for i=2,n do y = y * i end return y end local function xor(a,b) assert(a == 3 and b == 4) -- an exercise for the reader! return 7 -- or see https://lua-users.lua.ac.cn/wiki/BitUtils end debug.setmetatable(0, { -- create metatable for numbers __call = function(a, op) if op == '!' then return factorial(a) elseif op == 'xor' then return function(b) return xor(a,b) end end end }) print(- (5)'!' + 1, - (3) 'xor' (4)) --> -119 -7
注意运算符的优先级:这些实际上是函数调用。
在单目后缀运算符的情况下,没有内存分配,但二元运算符有。 我们可以通过以下方式改进它(尽管不幸的是,这可能现在依赖于未定义的行为)
local savea local function xorhelper(b) local a; a, savea = savea, nil return xor(a,b) end debug.setmetatable(0, { __call = function(a, op) if op == '!' then return factorial(a) elseif op == 'xor' then savea = a; return xorhelper end end })
--DavidManura,2007-07-14
cond ? expr1 : expr2
结构