2

在内部重载右关联运算符时,是否可以确定最左边的操作数?与此类似的东西。

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)
4

1 回答 1

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!

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

不管怎样,你可以看到,做这样的事情会引入一大堆新问题,这些问题很可能不值得他们付出努力来解决。

于 2013-06-03T13:59:31.463 回答