Created
April 14, 2014 20:14
-
-
Save leite/10679413 to your computer and use it in GitHub Desktop.
basic class simulacrum and basic hash object ... enjoy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- ---------------------------------------------------------------------------- | |
-- "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