From 84f3ae76ab0d7d4d46871155a8c3608e0e710315 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 2 Feb 2019 19:31:40 -0800 Subject: Added inverse dicts and a few new list methods. --- containers.lua | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 5 deletions(-) (limited to 'containers.lua') diff --git a/containers.lua b/containers.lua index e706831..cd3e7c0 100644 --- a/containers.lua +++ b/containers.lua @@ -1,4 +1,4 @@ -local List, Dict +local List, Dict, Undict, _undict_mt, _dict_mt local insert, remove, concat do local _obj_0 = table @@ -226,6 +226,23 @@ local _list_mt = { return _accum_0 end)()) end, + copy = function(self) + return List((function() + local _accum_0 = { } + local _len_0 = 1 + for i = 1, #self do + _accum_0[_len_0] = self[i] + _len_0 = _len_0 + 1 + end + return _accum_0 + end)()) + end, + reverse = function(self) + local n = #self + for i = 1, math.floor(n / 2) do + self[i], self[n - i + 1] = self[n - i + 1], self[i] + end + end, reversed = function(self) return List((function() local _accum_0 = { } @@ -236,6 +253,49 @@ local _list_mt = { end return _accum_0 end)()) + end, + sort = function(self) + return table.sort(self) + end, + sort_by = function(self, fn) + local keys = setmetatable({ }, { + __index = function(self, k) + local key = fn(k) + self[k] = key + return key + end + }) + return table.sort(self, function(a, b) + return keys[a] <= keys[b] + end) + end, + sorted = function(self) + local c = self:copy() + c:sort() + return c + end, + sorted_by = function(self, fn) + local c = self:copy() + c:sort_by(fn) + return c + end, + filter_by = function(self, keep) + local deleted = 0 + for i = 1, #self do + if not (keep(self[i])) then + deleted = deleted + 1 + elseif deleted > 0 then + self[i - deleted] = self[i] + end + end + for i = #self - deleted + 1, #self do + self[i] = nil + end + end, + filtered_by = function(self, keep) + local c = self:copy() + c:filter_by(keep) + return c end }, __newindex = function(self, k, v) @@ -262,7 +322,91 @@ List = function(t) return error("Unsupported List type: " .. type(t)) end end -local _dict_mt = { +local compliments = setmetatable({ }, { + __mode = 'k' +}) +_undict_mt = { + __index = function(self, k) + return not compliments[self][k] and true or nil + end, + __newindex = function(self, k, v) + if k then + compliments[self][k] = nil + else + compliments[self][k] = true + end + end, + __eq = function(self, other) + if not (type(other) == 'table' and getmetatable(other) == getmetatable(self)) then + return false + end + return compliments[self] == compliments[other] + end, + __len = function(self) + return math.huge + end, + __tostring = function(self) + return "~" .. _dict_mt.__tostring(compliments[self]) + end, + as_nomsu = function(self) + return "~" .. _dict_mt.as_nomsu(compliments[self]) + end, + as_lua = function(self) + return "~" .. __dict_mt.as_lua(compliments[self]) + end, + __band = function(self, other) + if getmetatable(other) == _undict_mt then + return Undict(_dict_mt.__bor(compliments[self], compliments[other])) + else + return _dict_mt.__band(other, self) + end + end, + __bor = function(self, other) + if getmetatable(other) == _undict_mt then + return Undict(_dict_mt.__band(compliments[self], compliments[other])) + else + return Undict((function() + local _tbl_0 = { } + for k, v in pairs(compliments[self]) do + if not other[k] then + _tbl_0[k] = v + end + end + return _tbl_0 + end)()) + end + end, + __bxor = function(self, other) + if getmetatable(other) == _undict_mt then + return _dict_mt.__bxor(compliments[self], compliments[other]) + else + return Undict(_dict_mt.__band(other, self)) + end + end, + __bnot = function(self) + return Dict((function() + local _tbl_0 = { } + for k, v in pairs(compliments[self]) do + _tbl_0[k] = v + end + return _tbl_0 + end)()) + end +} +Undict = function(d) + local u = setmetatable({ }, _undict_mt) + compliments[u] = Dict((function() + local _tbl_0 = { } + for k, v in pairs(d) do + if v then + _tbl_0[k] = true + end + end + return _tbl_0 + end)()) + return u +end +_dict_mt = { __type = "a Dict", __eq = function(self, other) if not (type(other) == 'table' and getmetatable(other) == getmetatable(self)) then @@ -292,7 +436,7 @@ local _dict_mt = { local _accum_0 = { } local _len_0 = 1 for k, v in pairs(self) do - _accum_0[_len_0] = "." .. tostring(k) .. " = " .. tostring(v) + _accum_0[_len_0] = v == true and "." .. as_nomsu(k) or "." .. tostring(k) .. " = " .. tostring(v) _len_0 = _len_0 + 1 end return _accum_0 @@ -303,7 +447,7 @@ local _dict_mt = { local _accum_0 = { } local _len_0 = 1 for k, v in pairs(self) do - _accum_0[_len_0] = "." .. tostring(as_nomsu(k)) .. " = " .. tostring(as_nomsu(v)) + _accum_0[_len_0] = v == true and "." .. as_nomsu(k) or "." .. tostring(as_nomsu(k)) .. " = " .. tostring(as_nomsu(v)) _len_0 = _len_0 + 1 end return _accum_0 @@ -320,11 +464,22 @@ local _dict_mt = { return _accum_0 end)(), ", ") .. "}" end, + as_list = function(self) + return List((function() + local _accum_0 = { } + local _len_0 = 1 + for k, v in pairs(self) do + _accum_0[_len_0] = k + _len_0 = _len_0 + 1 + end + return _accum_0 + end)()) + end, __band = function(self, other) return Dict((function() local _tbl_0 = { } for k, v in pairs(self) do - if other[k] ~= nil then + if other[k] then _tbl_0[k] = v end end @@ -332,6 +487,9 @@ local _dict_mt = { end)()) end, __bor = function(self, other) + if getmetatable(other) == _undict_mt then + return _undict_mt.__bor(other, self) + end local ret = Dict((function() local _tbl_0 = { } for k, v in pairs(self) do @@ -347,6 +505,9 @@ local _dict_mt = { return ret end, __bxor = function(self, other) + if getmetatable(other) == _undict_mt then + return _undict_mt.__bxor(other, self) + end local ret = Dict((function() local _tbl_0 = { } for k, v in pairs(self) do @@ -363,6 +524,7 @@ local _dict_mt = { end return ret end, + __bnot = Undict, __add = function(self, other) local ret = Dict((function() local _tbl_0 = { } -- cgit v1.2.3