Deprecated the emulation of '__le' using '__lt'

As hinted in the manual for Lua 5.3, the emulation of the metamethod
for '__le' using '__le' has been deprecated. It is slow, complicates
the logic, and it is easy to avoid this emulation by defining a proper
'__le' function.

Moreover, often this emulation was used wrongly, with a programmer
assuming that an order is total when it is not (e.g., NaN in
floating-point numbers).
This commit is contained in:
Roberto Ierusalimschy
2018-08-24 10:17:54 -03:00
parent f99509581e
commit 8c8a91f2ef
8 changed files with 44 additions and 40 deletions

View File

@@ -1,4 +1,4 @@
-- $Id: testes/coroutine.lua $
-- $Id: testes/coroutine.lua 2018-07-25 15:31:04 -0300 $
-- See Copyright Notice in file all.lua
print "testing coroutines"
@@ -619,10 +619,8 @@ end
assert(run(function () if (a>=b) then return '>=' else return '<' end end,
{"le", "sub"}) == "<")
-- '<=' using '<'
mt.__le = nil
assert(run(function () if (a<=b) then return '<=' else return '>' end end,
{"lt"}) == "<=")
{"le", "sub"}) == "<=")
assert(run(function () if (a==b) then return '==' else return '~=' end end,
{"eq"}) == "~=")
@@ -677,7 +675,7 @@ do -- a few more tests for comparsion operators
return val(a) < val(b)
end,
}
local mt2 = { __lt = mt1.__lt } -- no __le
local mt2 = { __lt = mt1.__lt, __le = mt1.__le }
local function run (f)
local co = coroutine.wrap(f)

View File

@@ -1,4 +1,4 @@
-- $Id: testes/events.lua $
-- $Id: testes/events.lua 2018-07-25 15:31:04 -0300 $
-- See Copyright Notice in file all.lua
print('testing metatables')
@@ -217,6 +217,13 @@ t.__lt = function (a,b,c)
return a<b, "dummy"
end
t.__le = function (a,b,c)
assert(c == nil)
if type(a) == 'table' then a = a.x end
if type(b) == 'table' then b = b.x end
return a<=b, "dummy"
end
function Op(x) return setmetatable({x=x}, t) end
local function test ()
@@ -236,15 +243,6 @@ end
test()
t.__le = function (a,b,c)
assert(c == nil)
if type(a) == 'table' then a = a.x end
if type(b) == 'table' then b = b.x end
return a<=b, "dummy"
end
test() -- retest comparisons, now using both `lt' and `le'
-- test `partial order'
@@ -266,14 +264,6 @@ t.__lt = function (a,b)
return next(b) ~= nil
end
t.__le = nil
assert(Set{1,2,3} < Set{1,2,3,4})
assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
assert((Set{1,2,3,4} <= Set{1,2,3,4}))
assert((Set{1,2,3,4} >= Set{1,2,3,4}))
assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
t.__le = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
@@ -281,10 +271,15 @@ t.__le = function (a,b)
return true
end
assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
assert(Set{1,2,3} < Set{1,2,3,4})
assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
assert((Set{1,2,3,4} <= Set{1,2,3,4}))
assert((Set{1,2,3,4} >= Set{1,2,3,4}))
assert(not (Set{1,3} <= Set{3,5}))
assert(not(Set{1,3} <= Set{3,5}))
assert(not(Set{1,3} >= Set{3,5}))
t.__eq = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
@@ -376,6 +371,7 @@ t1 = {}; c = {}; setmetatable(c, t1)
d = {}
t1.__eq = function () return true end
t1.__lt = function () return true end
t1.__le = function () return false end
setmetatable(d, t1)
assert(c == d and c < d and not(d <= c))
t2 = {}