Skip to content

Instantly share code, notes, and snippets.

@leite
Created April 14, 2014 20:14
Show Gist options
  • Save leite/10679413 to your computer and use it in GitHub Desktop.
Save leite/10679413 to your computer and use it in GitHub Desktop.
basic class simulacrum and basic hash object ... enjoy
-- ----------------------------------------------------------------------------
-- "THE BEER-WARE LICENSE" (Revision 42):
-- <[email protected]> wrote this file. As long as you retain this notice you
-- can do whatever you want with this stuff. If we meet some day, and you think
-- this stuff is worth it, you can buy me a beer in return
-- ----------------------------------------------------------------------------
local table, string = require [[table]], require [[string]]
local type, pairs, rawset, setmetatable, getmetatable =
type, pairs, rawset, setmetatable, getmetatable
local insert, remove, format = table.insert, table.remove, string.format
--
--
--
--
--
local classes = setmetatable({}, {__mode='k'})
local function deep_copy(t, dest)
local t, r = t or {}, dest or {}
for k,v in pairs(t) do
if type(v) == 'table' and k ~= '__index' then
r[k] = deep_copy(v)
else
r[k] = v
end
end
return r
end
local function is(self, klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m.super
end
return false
end
local function include(self, ...)
if not ... then return end
for k,v in pairs(...) do
if self[k] then self[k] = nil end
self[k] = v
end
end
local function extends(self, ...)
local meta = {}
if ... then deep_copy(..., deep_copy(self, meta)) else deep_copy(self, meta) end
setmetatable(meta, getmetatable(self))
return meta
end
local function new_index(self, key, value)
rawset(self, key, value)
for i=1, #classes[self] do
classes[self][i][key] = value
end
end
local function class(base)
local c, mt = {}, {}
if type(base) == 'table' then
for i,v in pairs(base) do c[i] = v end
c.super = base
end
c.__index = c
c.is = is
c.extends = extends
c.include = include
mt.__newindex = new_index
classes[c] = {}
mt.__call = function(self, ...)
local obj = {}
setmetatable(obj, c)
if c.__init then c.__init(obj, ...) end
return obj
end
if c.super then
insert(classes[c.super], c)
end
setmetatable(c, mt)
return c
end
--
--
--
--
--
local Hash = class()
Hash.__name = 'Hash'
function Hash:__init(bootstrap)
rawset(self, '_i', 0)
rawset(self, 'index', {})
if 'table' == type(bootstrap) then
for k,v in pairs(bootstrap) do
self.index[k] = v
end
end
end
function Hash:__newindex(key, val)
if not self.index[key] then
insert(self.index, key)
end
if nil == val then
for i=1, #self.index do
if self.index[i] == key then
remove(self.index, i)
self._i = self._i > 0 and (self._i - 1) or self._i
end
end
end
self.index[key] = val
end
function Hash:__index(key)
return self.index[key]
end
function Hash:__pairs()
self._i = 0
local function iter(self)
self._i = self._i + 1
local k = self.index[self._i]
if k then return k, self.index[k] end
end
return iter, self
end
function Hash:__len()
return #self.index
end
function Hash:__sub(hash)
if not('table' == type(hash) and
rawget((getmetatable(hash) or {}), '__name') == 'Hash') then
error(format("expecting hash, got a '%s'", type(hash)))
end
local new_index = {}
for i=1, #self.index do
if hash.index[self.index[i]] then
insert(new_index, self.index[i])
new_index[self.index[i]] = self.index[self.index[i]]
end
end
return getmetatable(self)(new_index)
end
function Hash:__add(hash)
if not('table' == type(hash) and
rawget((getmetatable(hash) or {}), '__name') == 'Hash') then
error(format("expecting hash, got a '%s'", type(hash)))
end
local new_hash = getmetatable(self)(self.index)
for i=1, #hash.index do
if not new_hash.index[hash.index[i]] then
new_hash[hash.index[i]] = hash.index[hash.index[i]]
end
end
return new_hash
end
local n, m = Hash(), Hash()
n['xico'] = 100
n['jose'] = 99
n['antonio'] = 'hey'
n['loco'] = 10.197
n.xico = 'Fuck!'
m.camila = 'Wow'
m.jose = 666
print(#n, n['xico'], n.antonio) print() -- 4 Fuck! hey
--[[
xico Fuck!
jose 99
antonio hey
]]
for k,v in pairs(n) do
if k == 'loco' then
n[k] = nil -- delete "loco"
else
print(k, v)
end
end print()
print(#n) print() -- 3
local g = n - m
local h = m - n
local z = n + m
local y = m + n
n.octopus = 'Genius'
-- jose 99
for k,v in pairs(g) do print(k, v) end print()
-- jose 666
for k,v in pairs(h) do print(k, v) end print()
--[[
xico Fuck!
jose 99
antonio hey
camila Wow
]]
for k,v in pairs(z) do print(k, v) end print()
--[[
camila Wow
jose 666
xico Fuck!
antonio hey
]]
for k,v in pairs(y) do print(k, v) end print()
--[[
xico Fuck!
jose 99
antonio hey
octopus Genius
]]
for k,v in pairs(n) do print(k, v) end print()
-- camila Wow
-- jose 666
for k,v in pairs(m) do print(k, v) end print()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment