lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


The object system that this thread reports on has to store the functions in
the instances because it seeks to eliminate the ":" syntax for method calls
and just use ".". That requires creating closures for all method calls and
unless one wants to pay the price of creating the closure at every call, one
has to generate per instance closures.

One interesting thing to try would be to use weak tables for the caches.
This would mean that repeated calls to the same method would probably get
optimized but the caches would get cleaned out eventually.

That being said, I don't feel nearly as strongly opposed to the : syntax as
some people.

Mark

on 12/9/04 7:44 AM, John Paquin at jpaquin@breakawaygames.com wrote:

> hmmm, so your storing your tables in the instance, not in the class
> definition?  doesn't that waste a lot of memory?
> 
> Couldn't we cache the functions in the class definition instead, then
> have the instance reference the class definition?  Then the definition's
> cache could still get flushed on reload but you wouldn't have to have a
> per instance cache.
> 
> Paul Du Bois wrote:
> 
>> You can do it; it just takes a little more effort on the part of your
>> reload() function. For instance, we don't really construct a c++ vtbl,
>> but we do cache objects in our instance tables after they've been
>> looked up from the chain of shared class tables.
>> 
>> Thus, one of the first things we do when reloading class C is to clear
>> out all cached functions from instance tables. You can tell cached
>> values by comparing rawget(instancetable, name) to
>> "normalget"(instancetable.Class, name).
>> 
>> Then we reload the class and let the caching catch up.
>> 
>> p
>> 
>> On Wed, 08 Dec 2004 12:20:31 -0500, John Paquin
>> <jpaquin@breakawaygames.com> wrote:
>>  
>> 
>>> with your class system, is it possible to change the lua code (lass.lua
>>> in this case), reload the lua file and expect to see the changes
>>> reflected in existing objects (like c in this case)?  This is a major
>>> downfall of my own class system because I create a table of methods for
>>> each class, much like C++ keeps a single table of virtual methods for
>>> each class.  Then all objects of that class reference this single table.
>>> 
>>> I think that the only way to incorporate dynamic changes is to
>>> dynamically (i.e. at the time of reference) follow the inheritance chain
>>> backward to find the correct method.
>>> 
>>> Sorry if this question has already been asked.
>>> 
>>> 
>>> 
>>> Raffaele Salmaso wrote:
>>> 
>>>    
>>> 
>>>> 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
>>>> 
>>>> 
>>>> 
>>>>      
>>>> 
>>>    
>>> 
>> 
>> 
>>  
>> 
>