lean2/tests/lua/map.lua

89 lines
2.5 KiB
Lua
Raw Normal View History

-- This examples demonstrates that Lean objects are not very useful as Lua table keys.
local f = Const("f")
local m = {}
local env = environment()
env:add_var("T", Type())
env:add_var("f", mk_arrow(Const("T"), Const("T")))
for i = 1, 100 do
env:add_var("a" .. i, Const("T"))
local t = f(Const("a" .. i))
-- Any object can be a key of a Lua table.
-- But, Lua does not use the method __eq for comparing keys.
-- The problem is that Lua uses its own hashcode that may not
-- be compatible with the __eq implemantion.
-- By non-compatible, we mean two objects my be equal by __eq, but
-- the hashcodes may be different.
m[t] = i
end
for t1, i in pairs(m) do
local t2 = f(Const("a" .. i))
-- print(t1, i, t2)
assert(m[t1] == i)
-- t1 and t2 are structurally equal
assert(t1 == t2)
-- t1 and t2 are different objects
assert(not t1:is_eqp(t2))
-- t2 is not a key of map
assert(m[t2] == nil)
assert(env:normalize(t1) == t1)
assert(t1:instantiate(Const("a")) == t1)
local t1_prime = t1:instantiate(Const("a"))
-- t1 and t1_prime are structurally equal
assert(t1 == t1_prime)
-- Moreover, they are references to the same Lean object
assert(t1:is_eqp(t1_prime))
-- But, they are wrapped by different Lua userdata
assert(m[t1_prime] == nil)
end
-- We can store elements that implement __lt and __eq metamethods in splay_maps.
-- The implementation assumes that the elements stored in the splay map can be totally ordered by __lt
m = splay_map()
m:insert(Const("a"), 10)
assert(m:contains(Const("a")))
assert(not m:contains(Const("b")))
assert(m:find(Const("a")) == 10)
local a, b = Consts("a, b")
m:insert(f(a, b), 20)
assert(m:find(f(a, b)) == 20)
assert(m:find(f(a, a)) == nil)
assert(m:size() == 2)
assert(#m == 2)
m:erase(f(a, a))
assert(m:size() == 2)
m:erase(f(a, b))
assert(m:size() == 1)
for i = 1, 100 do
local t = f(Const("a" .. i))
m:insert(t, i)
assert(m:contains(t))
assert(m:find(t) == i)
end
assert(m:size() == 101)
for i = 1, 100 do
local t = f(Const("a" .. i))
assert(m:find(t) == i)
end
-- The following call fails because integers cannot be compared with Lean expressions
assert(not pcall(function() m:insert(10, 20) end))
-- Splay maps copy operation is O(1)
local m2 = m:copy()
m2:insert(b, 20)
assert(m:size() == 101)
assert(m2:size() == 102)
-- We can also traverse all elements in the map
local num = 0
m:for_each(
function(k, v)
print(tostring(k) .. " -> " .. v)
num = num + 1
end
)
assert(num == 101)