|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- eoo.lua: Edrx'x simple OO scheme.
-- Documentation: (find-dn6 "eoo.lua")
-- (find-dn6 "eoo.lua" "__mt")
--
-- This file:
-- http://angg.twu.net/blogme4/eoo.lua.html
-- http://angg.twu.net/blogme4/eoo.lua
-- (find-blogme4file "eoo.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2011jan12
-- 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")
-- Inheritance: (find-dn5 "eoo.lua")
-- Announcement: http://lua-users.org/lists/lua-l/2011-03/msg00975.html
-- «.test-eoo» (to "test-eoo")
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
-- 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 "~/blogme4/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
--
--]==]
-- Local Variables:
-- coding: raw-text-unix
-- ee-anchor-format: "«%s»"
-- End: