Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://angg.twu.net/LUA/Set.lua.html
--   http://angg.twu.net/LUA/Set.lua
--           (find-angg "LUA/Set.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- The classes Set and SetL.
--
-- Objects of the class "Set" can be used in two ways: either as sets
-- in the traditional sense or in a way in which the elements of the
-- set are treated as the keys of an associative table and each key is
-- associated to a value. When a Set object is used as a set "in the
-- traditional sense" the keys of the table correspond to the elements
-- of the set and the value associated to each key is the key itself.
--
-- The class SetL is a variant of Set in which we record the order in
-- which the keys were added.
--
-- TODO: document this.
--
-- (find-ydb "ydb2.lua" "SetL")
-- (find-ydb "ydb2.lua" "SetL-tests")
-- (find-fline "~/lakhesys/TODO" "SetL =")
-- (find-es "lua5" "SetL")

-- «.Set»		(to "Set")
-- «.Set-tests»		(to "Set-tests")
-- «.SetL»		(to "SetL")
-- «.SetL-tests»	(to "SetL-tests")




--  ____       _   
-- / ___|  ___| |_ 
-- \___ \ / _ \ __|
--  ___) |  __/ |_ 
-- |____/ \___|\__|
--                 
-- «Set»  (to ".Set")
-- Also here: (find-angg "LUA/lua50init.lua" "Set")
--
Set = Class {
  type = "Set",
  new  = function () return Set {_={}} end,
  from = function (L) return Set.fromarray(L) end,
  fromarray = function (L)
      local C = Set.new()
      for i,v in ipairs(L) do C._[v]=v end
      return C
    end,
  __add = function (A, B)   -- union
      local C = Set.new()
      for k,v in pairs(A._) do C._[k]=v end
      for k,v in pairs(B._) do C._[k]=v end
      return C
    end,
  __sub = function (A, B)   -- difference
      local C = Set.new()
      for k,v in pairs(A._) do C._[k]=v end
      for k,v in pairs(B._) do C._[k]=nil end
      return C
    end,
  __mul = function (A, B)     -- intersection
      local C = Set.new()
      for k,v in pairs(A._) do if B._[k] then C._[k]=v end end
      return C
    end,
  __len = function (A) print"!" return #(keys(A._)) end,  -- number of elements
  __tostring = function (A)
      return "(Set with "..A:n().." elements)"
    end,
  --
  -- Methods
  __index = {
    get = function (A, k) return A._[k] end,
    has = function (A, k) return A._[k] end,
    n   = function (A) return #keys(A._) end,
    k   = function (A) return  keys(A._) end,
    ks  = function (A) return sorted(keys(A._)) end,
    ksc = function (A, sep) return table.concat(A:ks(), sep or "\n") end,
    gen = function (A)
        return cow(function ()
            for _,k in ipairs(A:ks()) do coy(k, A:get(k)) end
          end)
      end,
    add = function (A, key, val)
        A._[key] = val or key
        return A
      end,
    del = function (A, key)
        A._[key] = nil
        return A
      end,
  },
}



-- «Set-tests»  (to ".Set-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Set.lua"

tokeyval = function (str)
    local k,v = str:match"(.-)->(.*)"
    if k then return k,v else return str end
  end
Set.__index.adds = function (s, str)
    for _,str in ipairs(split(str)) do s:add(tokeyval(str)) end
    return s
  end
Set.__index.print = function (A) for k,v in A:gen() do print(k.."->"..v) end end

A = Set.new():adds("1 2->22 3->33")          -- the "1" works as "1->1"
B = Set.new():adds("3->333 4->444 5->555")
= A
= A:ksc()
PPV(A)
= (A*B):ksc" "
= (A+B):ksc" "
= (A-B):ksc" "

 A   :print()
   B :print()
(A*B):print()   -- here the output is "3->33", not "3->333"
(A+B):print()   -- note the "3->333" (not "3->33"!) in the output
(A-B):print()

--]]




--  ____       _   _     
-- / ___|  ___| |_| |    
-- \___ \ / _ \ __| |    
--  ___) |  __/ |_| |___ 
-- |____/ \___|\__|_____|
--                       
-- «SetL»  (to ".SetL")
-- Also here: (find-angg "LUA/lua50init.lua" "SetL")
--
SetL = Class {
  type = "SetL",
  new  = function () return SetL {keys={}, list={}} end,
  from = function (L) return Set.fromarray(L) end,
  fromarray = function (L)
      local C = Set.new()
      for i,k in ipairs(L) do C:add(k) end
      return C
    end,
  __len = function (setl) return setl:n() end,
  __tostring = function (setl)
      return format("(SetL with %d elements)", setl:n())
    end,
  __add = function (A, B)   -- union
      local C = SetL:new()
      for k,v in A:gen() do C:add(k, v) end
      for k,v in B:gen() do C:add(k, v) end
      return C
    end,
  __mul = function (A, B)   -- intersection
      local C = SetL:new()
      for k,v in A:gen() do if B:has(k) then C:add(k, v) end end
      return C
    end,
  __sub = function (A, B)   -- difference
      local C = SetL.new()
      for k,v in A:gen() do if not B:has(k) then C:add(k, v) end end
      return C
    end,
  --
  -- Methods
  __index = {
    has = function (setl, key) return setl.keys[key] end,
    val = function (setl, key) return setl.keys[key] end,
    n   = function (setl) return #setl.list end,
    k   = function (setl) return setl.list end,
    ks  = function (setl) return sorted(keys(setl.keys)) end,
    ksc = function (setl, sep) return table.concat(setl:ks(), sep or "\n") end,
    gen = function (setl) return cow(function ()
        for i,k in ipairs(setl.list) do coy(k, setl:val(k)) end
      end) end,
    add = function (setl, key, val)
        if not setl:has(key) then
          setl.keys[key] = val or key
          table.insert(setl.list, key)
        end
        return setl
      end,
  },
}

-- «SetL-tests»  (to ".SetL-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "SetL.lua"

--]]







-- Local Variables:
-- coding:  utf-8-unix
-- End: