使用元表添加两种不同类型

问题描述 投票:0回答:1

我有分数表,它存储分数,分数与其元表相关联。

fraction.add
是元操作 (
__add
)。 问题就在这里。我想计算 x + y。

如果 x 和 y 都是分数,那么对其求值就没有问题。它通过

farction.add
进行评估。

如果x和y都是数字,不是分数,那么就是简单的数字加法,与分数无关。

如果 x 是分数,y 是非分数(反之亦然),那么我想将分数 x 转换为数字并将其添加到 y。我当然可以轻松地将分数转换为数字,但问题在于与

__add
相关的分数的
fraction.add
元表。仅当 x 和 y 均为分数时才有效。它会抛出错误,因为 y 不是分数。所以我正在寻找一种逻辑来处理当一个是分数而另一个是非分数时的情况。 if else 在元表中可能很简单,但我无法做到。任何想法都会很有帮助。

lua operators lua-table evaluation
1个回答
0
投票

我已经实现了一个成熟的这样的

fraction
“类”并对此提供支持。就像检查
a, b
元方法的参数
__add
的类型并根据需要将它们转换为分数一样简单。

或者,举一个更简单的例子,它忽略了几点:

  • 分数不会被缩短。浮点/整数不精确/溢出最终会导致分数不准确。理想情况下,您应该使用某种大整数作为分子和分母,并在每次运算后缩短。
  • 为了简单起见,只有整数才会转换为分数;浮点数会引发错误,因为将浮点数转换为分数更加棘手。
  • 缺少大量操作。
local fraction_mt = {}

local function new_fraction(numerator, denominator)
    assert(numerator % 1 == 0)
    assert(denominator % 1 == 0)
    return setmetatable({numerator = numerator, denominator = denominator}, fraction_mt)
end

local function add_fractions(a, b)
    -- Note: No care is taken to shorten the resulting fraction here.
    return new_fraction(a.numerator * b.denominator + b.numerator * a.denominator,
        a.denominator * b.denominator)
end

function fraction_mt.__add(a, b)
    if type(a) == "number" then
        a = new_fraction(a, 1)
    elseif type(b) == "number" then
        b = new_fraction(b, 1)
    end
    return add_fractions(a, b)    
end

function fraction_mt:__tostring()
    return ("%d/%d"):format(self.numerator, self.denominator)
end

print(new_fraction(1, 2) + new_fraction(1, 2)) -- 4/4
print(new_fraction(1, 2) + 1) -- 3/2
print(1 + new_fraction(1, 2)) -- 3/2

请注意,即使只有一个操作数不是数字,Lua 也会调用

__add
(请参阅参考手册):

如果加法的任何操作数不是数字,Lua将尝试调用元方法。它首先检查第一个操作数(即使它是一个数字);如果该操作数没有为 __add 定义元方法,那么 Lua 将检查第二个操作数。如果Lua能找到一个元方法,它就会以两个操作数为参数调用该元方法,调用的结果(调整为一个值)就是操作的结果。否则,如果没有找到元方法,Lua 会引发错误。

© www.soinside.com 2019 - 2024. All rights reserved.