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

在内部重载从右向左结合的运算符时,是否有可能确定左侧的操作数?类似于以下方式:

MyClass.__concat(left, right)
  if is_leftmost_operand(left) then
    -- 做这个
  else
    -- 做那个
  end
end

你可以像平常一样调用 add ,而不需要设置某种类型的标志或者其他东西:

instance1..instance2..instance3

我想要 __concat 的从右向左结合行为,但是当在链的开头时,我想要发生不同的事情。

编辑:

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

instance1..instance2..(instance3..instance4..instance5)
点赞
用户1244588
用户1244588

在进行下文之前,我 强烈 建议您对于您打算使用最左边的运算符进行的任何特殊操作使用额外的操作。__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("最右边的运算:", 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; -- b .. x运算不会被检测到最右边!

您可能可以通过在每个时钟周期重置注册表来解决我指出的问题,但实际上这种行为会使操作更可预测。或者至少在我看来。

不管怎样,您可以看到这样做会引入一堆新问题,这些问题很可能不值得解决所花费的努力。

2013-06-03 13:59:31