This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.
Programming in Lua | ||
Part II. Tables and Objects Chapter 13. Metatables and Metamethods |
Metatables also allow us to give meaning to the relational operators,
through the metamethods __eq
(equality),
__lt
(less than), and __le
(less or equal).
There are no separate metamethods for the
other three relational operators,
as Lua translates a ~= b
to not (a == b)
,
a > b
to b < a
, and a >= b
to b <= a
.
(Big parentheses:
Until Lua 4.0, all order operators were translated to a single one,
by translating a <= b
to not (b < a)
.
However, this translation is incorrect when we have a
partial order,
that is, when not all elements in our type are properly ordered.
For instance,
floating-point numbers are not totally ordered in most machines,
because of the value Not a Number (NaN).
According to the IEEE 754 standard,
currently adopted by virtually every hardware,
NaN represents undefined values, such as the result of 0/0
.
The standard specifies that any comparison that
involves NaN should result in false.
That means that NaN <= x
is always false,
but x < NaN
is also false.
That implies that the translation from a <= b
to not (b < a)
is not valid in this case.)
In our example with sets, we have a similar problem.
An obvious (and useful) meaning for <=
in sets is set containment:
a <= b
means that a
is a subset of b
.
With that meaning,
again it is possible that both a <= b
and
b < a
are false;
therefore, we need separate implementations for
__le
(less or equal) and __lt
(less than):
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) endFinally, we can define set equality through set containment:
Set.mt.__eq = function (a,b) return a <= b and b <= a endAfter those definitions, we are now ready to compare sets:
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
Unlike arithmetic metamethods, relational metamethods do not support mixed types. Their behavior for mixed types mimics the common behavior of these operators in Lua. If you try to compare a string with a number for order, Lua raises an error. Similarly, if you try to compare two objects with different metamethods for order, Lua raises an error.
An equality comparison never raises an error, but if two objects have different metamethods, the equality operation results in false, without even calling any metamethod. Again, this behavior mimics the common behavior of Lua, which always classifies strings as different from numbers, regardless of their values. Lua calls the equality metamethod only when the two objects being compared share this metamethod.
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. |