第一版是针对 Lua 5.0 编写的。虽然对后续版本仍然有很大参考价值,但还是有一些不同。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目。
用 Lua 编程 | ||
第二部分。表和对象 第 13 章。元表和元方法 |
元表还允许我们通过元方法 __eq
(相等)、__lt
(小于)和 __le
(小于或等于)赋予关系运算符含义。没有针对其他三个关系运算符的单独元方法,因为 Lua 将 a ~= b
转换为 not (a == b)
,将 a > b
转换为 b < a
,将 a >= b
转换为 b <= a
。
(大括号:在 Lua 4.0 之前,所有顺序运算符都转换为单个运算符,方法是将 a <= b
转换为 not (b < a)
。但是,当我们有偏序(即我们类型中的所有元素未正确排序)时,此转换不正确。例如,由于非数字(NaN)值,大多数机器中的浮点数并未完全排序。根据目前几乎所有硬件采用的 IEEE 754 标准,NaN 表示未定义的值,例如 0/0
的结果。该标准规定,涉及 NaN 的任何比较都应导致 false。这意味着 NaN <= x
始终为 false,但 x < NaN
也为 false。这意味着从 a <= b
到 not (b < a)
的转换在这种情况下无效。)
在我们的集合示例中,我们遇到了类似的问题。<=
在集合中一个显而易见(且有用的)含义是集合包含:a <= b
表示 a
是 b
的子集。有了这个含义,a <= b
和 b < a
都有可能是假值;因此,我们需要为 __le
(小于或等于)和 __lt
(小于)提供单独的实现
Set.mt.__le = function (a,b) -- set containment for k in pairs(a) do if not b[k] then return false end end return true end Set.mt.__lt = function (a,b) return a <= b and not (b <= a) end最后,我们可以通过集合包含来定义集合相等
Set.mt.__eq = function (a,b) return a <= b and b <= a end在这些定义之后,我们现在可以比较集合了
s1 = Set.new{2, 4} s2 = Set.new{4, 10, 2} print(s1 <= s2) --> true print(s1 < s2) --> true print(s1 >= s1) --> true print(s1 > s1) --> false print(s1 == s2 * s1) --> true
与算术元方法不同,关系元方法不支持混合类型。它们对混合类型的行为模仿了 Lua 中这些运算符的常见行为。如果您尝试比较一个字符串和一个数字的顺序,Lua 会引发一个错误。同样,如果您尝试比较两个具有不同元方法的对象的顺序,Lua 会引发一个错误。
相等比较永远不会引发错误,但是如果两个对象具有不同的元方法,相等操作将导致 false,甚至不会调用任何元方法。同样,此行为模仿了 Lua 的常见行为,它总是将字符串归类为与数字不同,无论其值如何。Lua 仅在被比较的两个对象共享此元方法时才会调用相等元方法。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |