local immutable = require"immutable" local bright = string.char(27).."[1m" local blue = string.char(27).."[34m" local reset = string.char(27).."[0m" local function say(...) io.write(bright..blue); print(...); io.write(reset); end local function repr(t) local tmp = {} for k,v in pairs(t) do tmp[#tmp+1] = ("%s=%s"):format(k,v) end return "{"..table.concat(tmp, ", ").."}" end local Vec = immutable({"x","y"}, { len2=function(self) return self.x*self.x + self.y*self.y end, }, { __add=function(self, other) local cls = getmetatable(self) return cls(self.x+other.x, self.y+other.y) end, __tostring=function(self) return "Vec("..tostring(self.x)..", "..tostring(self.y)..")" end, }) local v = Vec(1,3) say(v) local also_v = Vec(1,3) say(also_v) -- Hash collision right now local not_v = Vec(true,3) say(not_v) local also_not_v = Vec(true,3) say(also_not_v) say(v == also_v) say(v + Vec(5,6)) collectgarbage() say(Vec("hello", "world")) say(Vec("hello", "world")) collectgarbage() collectgarbage() say("Let's look at the instances") for h,b in pairs(Vec.__instances) do say(("Hash bucket: 0x%x"):format(h)) for k,v in pairs(b) do local tmp = {} for kk,vv in pairs(v) do tmp[#tmp+1] = tostring(vv) end say(' <'..table.concat(tmp, ", ")..'>') end end local FooVec = immutable({"x","y"}, { len2=function(self) return self.x*self.x + self.y*self.y end, }, { __add=function(self, other) local cls = getmetatable(self) return cls(self.x+other.x, self.y+other.y) end, __tostring=function(self) return "Vec("..tostring(self.x)..", "..tostring(self.y)..")" end, }) say("FooVec: "..tostring(FooVec(1,3))) say("FooVec == Vec: "..tostring(FooVec(1,3) == Vec(1,3))) say("FooVec:len2() = "..tostring(FooVec(1,3):len2()))