Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- eoo.lua: Edrx'x simple OO scheme.
-- This file:
--   http://angg.twu.net/dednat5/eoo.lua.html
--   http://angg.twu.net/dednat5/eoo.lua
--                    (find-dn5 "eoo.lua")
-- (find-tkdiff "~/blogme4/eoo.lua" "~/dednat5/eoo.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2011nov21
-- License: GPL3
--
-- A very simple object system.
-- The metatable of each object points to its class,
-- and classes are callable, and act as creators.
-- New classes can be created with, e.g.:
--   Circle = Class { type = "Circle", __index = {...} }
-- then:
--   Circle {size = 1}
-- sets the metatable of the table {size = 1} to Circle,
-- and returns the table {size = 1} (with its mt modified).
--
-- Originally from: (find-angg "LUA/canvas2.lua"  "Class")
-- A tool:          (find-angg ".emacs.templates" "class")

-- «.test-eoo»		(to "test-eoo")
-- «.box-diagram»	(to "box-diagram")


Class = {
    type   = "Class",
    __call = function (class, o) return setmetatable(o, class) end,
  }
setmetatable(Class, Class)

otype = function (o)  -- works like type, except on my "objects"
    local  mt = getmetatable(o)
    return mt and mt.type or type(o)
  end


-- Code for inheritance (2011nov21), untested...
-- The examples of usage for this are coming soon!
over = function (uppertable)
    return function (lowertable)
        setmetatable(uppertable, {__index=lowertable})
        return uppertable
      end
  end

ClassOver = function (upperclassmt)
    return function (lowerclass)
        setmetatable(upperclassmt.__index, {__index=lowerclass.__index})
        return Class(upperclassmt)
      end
  end




-- dump-to: tests
-- «test-eoo»  (to ".test-eoo")
--[==[
-- Here is a detailed explanation of how this works.
-- Using the notation of the __mt patch, at:
--       http://angg.twu.net/__mt.html
--                 (find-TH "__mt")
-- we can rewrite the code above as:
--   Class = { type   = "Class",
--             __call = \ (class, o) => o.__mt = class end }
--   Class.__mt = Class
--   otype = \ (o) local mt = o.__mt; => mt and mt.type or type(o) end
-- Here is a test for it (note: it does _not_ require a patched Lua).

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
ee_dofile "~/dednat5/eoo.lua"   -- this file
Vector = Class {
  type       = "Vector",
  __add      = function (V, W) return Vector {V[1]+W[1], V[2]+W[2]} end,
  __tostring = function (V) return "("..V[1]..","..V[2]..")" end,
  __index    = {
    norm = function (V) return math.sqrt(V[1]^2 + V[2]^2) end,
  },
}
v = Vector  {3,  4}  --  v = { 3,  4, __mt = Vector}
w = Vector {20, 30}  --  w = {20, 30, __mt = Vector}
print(v)             --> (3,4)
print(v + w)         --> (23,34)
print(v:norm())      --> 5
print( type(v))      --> table
print(otype(v))      --> Vector
print( type(""))     --> string
print(otype(""))     --> string

-- So we have:
--
--   Class  = {
--     type       = "Class",
--     __call     = \(class, o) => o.__mt = class end,
--     __mt       = Class
--   }
--   Vector = {
--     type       = "Vector",
--     __add      = \(V, W) => {V[1]+W[1], V[2]+W[2]} end,
--     __tostring = \(V) => "("..V[1]..","..V[2]..")" end,
--     __index    = { norm = \(V) => math.sqrt(V[1]^2+V[2]^2) end },
--     __mt       = Class
--   }
--
-- and we can use reductions to understand "Vector {3, 4}" and "v:norm()":
--
--   v   = Vector {3, 4}
--   --~-> Vector({3, 4})
--   --~-> Vector.__mt.__call(Vector, {3, 4})
--   --~->       Class.__call(Vector, {3, 4})
--   --~-> (\(class, o) =>      o.__mt = class  end)(Vector, {3, 4})
--   --~->         (\() => {3, 4}.__mt = Vector end)()
--   --~->                 {3, 4, __mt = Vector}
--
-- and:
--   
--   v:norm()
--   --~->  {3, 4, __mt=Vector}:norm()
--   --~->  {3, 4, __mt=Vector}.norm             ({3, 4, __mt=Vector})
--   --~->  {3, 4, __mt=Vector}.__mt.__index.norm({3, 4, __mt=Vector})
--   --~->                    Vector.__index.norm({3, 4, __mt=Vector})
--   --~-> (\(V) => math.sqrt(V[1]^2+V[2]^2) end)({3, 4, __mt=Vector})
--   --~->  (\() => math.sqrt(   3^2+   4^2) end)()
--   --~->  (\() =>                  5       end)()
--   --~->                           5

-- «box-diagram»  (to ".box-diagram")
-- Here is a box diagram that explains more clearly what we get after
-- running "v = Vector {3, 4}; w = Vector {20, 30}".
-- 
--   <fcal> = function (class, o) return setmetatable(o, class) end
--   <fadd> = function (V, W)     return Vector {V[1]+W[1], V[2]+W[2]} end
--   <ftos> = function (V)        return "("..V[1]..","..V[2]..")" end,
--   <fnor> = function (V)        return math.sqrt(V[1]^2 + V[2]^2) end
-- 
--            /---+---\       /---+----\
--        v = | 1 : 3 |   w = | 1 : 20 |
--            | 2 : 4 |       | 2 : 30 |
--            \mt-+---/       \mt-+----/
--              :  ............/
--              : /
--              vv
--            /--------------+----------\
--   Vector = | "type"       : "Vector" |
--            | "__add"      : <fadd>   |
--            | "__tostring" : <ftos>   |    /--------+--------\
--            | "__index"    :    * .......> | "norm" : <fnor> |
--            \mt------------+----------/    \--------+--------/
--              :
--              v
--            /----------+---------\
--    Class = | "type"   : "Class" |
--            | "__call" : <fcal>  |
--            \mt--------+---------/
--              :    ^
--              \..../
-- 
-- If we define precisely what is a "Class box" we can represent the
-- main part of the diagram above more compactly, as:
-- 
--            /---+---\       /---+----\
--        v = | 1 : 3 |   w = | 1 : 20 |
--            | 2 : 4 |       | 2 : 30 |
--            \mt-+---/       \mt-+----/
--              :  ............/
--              : /
--              vv
--            /-Class--------+----------\
--   Vector = | "type"       : "Vector" |
--            | "__add"      : <fadd>   |
--            | "__tostring" : <ftos>   |
--            +--------------+----------|
--            | "norm"       : <fnor>   |
--            \--------------+----------/
--
--]==]






-- Local Variables:
-- coding:             raw-text-unix
-- ee-anchor-format:   "«%s»"
-- End: