89 lines
2.5 KiB
Lua
89 lines
2.5 KiB
Lua
|
-- 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)
|