Raffaele Salmaso wrote:
[snip]
Ok, final draft. I think it is the best version. I improved the speed a
lot, using David's idea. Now I cache the function object directly in 
the instance object itself, so the overhead is very minimal, only the 
first time. I've also removed the table ~= klass test, which is always 
true (thanks Rici).
This is what I get with the last version
16:19:36 Mer Dic 08 raf@ice ~
$ cat klass.lua
...
object = class()
function object.test_loop(self)
    return 1
end
...
c=child()
for i=1,10000 do
    c.test_loop()
end
16:19:36 Mer Dic 08 raf@ice ~
$ time lua klass.lua
real    0m0.372s
user    0m0.140s
sys     0m0.010s
16:19:42 Mer Dic 08 raf@ice ~
$ time lua klass.lua
real    0m0.266s
user    0m0.130s
sys     0m0.030s
16:19:43 Mer Dic 08 raf@ice ~
$ time lua klass.lua
real    0m0.238s
user    0m0.120s
sys     0m0.030s
And here is what I get with a similar python code
16:24:02 Mer Dic 08 raf@ice ~
$ cat class.py
class object:
        def method(self):
                return 1
o=object()
for x in xrange(10000):
        o.method()
16:24:09 Mer Dic 08 raf@ice ~
$ time python2.4 class.py
real    0m0.309s
user    0m0.130s
sys     0m0.080s
16:24:10 Mer Dic 08 raf@ice ~
$ time python2.4 class.py
real    0m0.296s
user    0m0.090s
sys     0m0.080s
16:24:11 Mer Dic 08 raf@ice ~
$ time python2.4 class.py
real    0m0.295s
user    0m0.130s
sys     0m0.040s
So the results are very similar, if not the same.
Hope it can be useful.
------------------------------------------------------------------------
--
-- Copyright (C) 2004, Salmaso Raffaele <raffaele@salmaso.org>
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
--  1. Redistributions of source code must retain the above copyright notice,
--     this list of conditions and the following disclaimer.
--  2. Redistributions in binary form must reproduce the above copyright
--     notice, this list of conditions and the following disclaimer in the
--     documentation and/or other materials provided with the distribution.
--  3. If the binary program depends on a modified version of this package,
--     you are encouraged to publicly release the modified version of this
--     package.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
-- operator overloading
-- __add +
-- __mul *
-- __sub -
-- __div /
-- __le <=
-- __lt <
-- __eq ==
-- __tostring
-- __call ()
-- __index []
-- __newindex
-- __pow ^
-- __unm
-- __concat ..
-- IMPORTANT: operators are NOT inherited!
function class(super)
   -- create a new class description
   local klass = {}
   -- set the superclass (for object inheritance)
   setmetatable(klass, {
       __index = super,
       __call = function(self, ...)
           local tmp = {}
           setmetatable(tmp, klass)
           if self.init then
               self.init(tmp, unpack(arg))
           end
           return tmp
       end
   })
   klass.__index = function(table, key)
       local r = klass[key]
       if type(r) == 'function' then
           local f = function(...) return r(table, unpack(arg)) end
           table[key] = f
           return f
       else
           return r
       end
   end
   return klass
end
-- ######################
-- test the object system
-- ######################
object = class()
object.id = 42
function object.init(self)
   self.x = 0
end
function object.test_loop(self)
   return 1
end
function object.__tostring(self)
   return '' .. self.x
end
function object.print(self)
   print(self.x)
end
function object.__add(self, other)
   return self.x + other
end
child = class(object)
function child.init(self)
   object.init(self)
   self.x = 10
end
function child.__tostring(self)
   return '' .. self.id .. ' ' .. self.x
end
function child.__add(self, other)
   return self.x + other
end
c=child()
c.print()
print(c)
c=c+30
print(c)
for i=1,10000 do
   c.test_loop()
end