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 に答える