重载__concat时确定最左边的操作数

时间:2013-06-02 19:21:30

标签: lua

在内部重载右关联运算符时,是否可以确定最左边的操作数?有点像这样。

MyClass.__concat(left, right)
  if is_leftmost_operand(left) then
    -- do stuffs
  else
    -- do other stuffs
  end
end

你可以像往常一样调用add而不设置某种旗帜或其他东西。

instance1..instance2..instance3

我想要__concat的正确联想行为,但我想在链的开头发生不同的事情。

编辑:

为了澄清,在下面的表达式中instance1instance3都将被视为最左边的操作数。

instance1..instance2..(instance3..instance4..instance5)

1 个答案:

答案 0 :(得分:1)

在我进入此之前,我会强烈建议使用额外的操作来处理与最左边的操作符有关的任何特殊操作。 __unm__len是明显的选择,因为它们是一元的。例如,您的陈述可能看起来像

local x = -(a .. b .. c)

这将使您的代码更好地遵循,否则您的连接操作将不可替代,并且还会失去默认..运算符的关联性。我的意思是,根据您的预期操作,这些方程式将成立:

a .. b .. c ~= a .. (b .. c)
(a .. b ) .. c ~= a .. (b .. c)

话虽如此:我认为你不能在Lua中检测到最左边的操作 - 至少在分配之前,但你可以种类检测最右边的操作。

由于你没有准确写出你打算做什么,我只想指出你的操作可能会被改变,以便你以不同的方式处理最右边的操作,并获得相同的结果。结束,所以这里是一些示例代码

local MT = {};
local registry = setmetatable({}, {__mode == "k"});

function MT.__concat(left, right)
    if not registry[right] then
        print("rightmost operation", left, right);
    end

    local r = newTT(left.val .. right.val);
    registry[r] = true;

    return r;
end

function MT:__tostring()
    return tostring(self.val);
end

function newTT(v)
    return setmetatable({ val = v }, MT);
end

local a = newTT("A");
local b = newTT("B");
local c = newTT("C");
local d = newTT("D");

local x = a .. (b .. c) .. d;
local y = a .. (c .. b) .. d;
local z = a .. b .. x; -- the b .. x op will not be detected as rightmost!

你可以通过在每个tick上重置注册表来解决我在最后一行中指出的问题,但实际上这种行为会使操作更具可预测性。或者至少在我眼里。

嗯,无论如何,你可以看到做这些事情引入了一大堆新问题,这些问题很可能不值得他们解决。